Index: sys/arm64/arm64/gic_v3_its.c =================================================================== --- sys/arm64/arm64/gic_v3_its.c +++ sys/arm64/arm64/gic_v3_its.c @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -84,6 +85,8 @@ MALLOC_DEFINE(M_GIC_V3_ITS, "GICv3 ITS", GIC_V3_ITS_DEVSTR); +typedef uint32_t (*its_devid_func_t)(device_t); + static int its_alloc_tables(struct gic_v3_its_softc *); static void its_free_tables(struct gic_v3_its_softc *); static void its_init_commandq(struct gic_v3_its_softc *); @@ -98,12 +101,19 @@ static void its_cmd_mapi(struct gic_v3_its_softc *, struct its_dev *, uint32_t); static void its_cmd_inv(struct gic_v3_its_softc *, struct its_dev *, uint32_t); static void its_cmd_invall(struct gic_v3_its_softc *, struct its_col *); +static uint32_t its_quirk_devid_thunder(device_t); static void lpi_init_conftable(struct gic_v3_its_softc *); static void lpi_bitmap_init(struct gic_v3_its_softc *); static void lpi_init_cpu(struct gic_v3_its_softc *); static int lpi_config_cpu(struct gic_v3_its_softc *); +struct its_quirks { + uint64_t cpuid; + uint64_t cpuid_mask; + its_devid_func_t devid_func; +}; + const char *its_ptab_cache[] = { [GITS_BASER_CACHE_NCNB] = "(NC,NB)", [GITS_BASER_CACHE_NC] = "(NC)", @@ -133,6 +143,19 @@ [GITS_BASER_TYPE_RES7] = "Reserved (7)", }; +static struct its_quirks its_quirks[] = { + { + .cpuid = CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0), + .cpuid_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .devid_func = its_quirk_devid_thunder, + }, + { + .cpuid = 0, + .cpuid_mask = 0, + .devid_func = NULL, + } +}; + static struct gic_v3_its_softc *its_sc; #define gic_its_read(sc, len, reg) \ @@ -141,6 +164,68 @@ #define gic_its_write(sc, len, reg, val) \ bus_write_##len(&sc->its_res[0], reg, val) +static uint32_t +its_quirk_devid_thunder(device_t pci_dev) +{ + int bsf; + uint32_t bus; + + bus = pci_get_bus(pci_dev); + + bsf = PCI_RID(pci_get_bus(pci_dev), pci_get_slot(pci_dev), + pci_get_function(pci_dev)); + + /* ECAM is on bus=0 */ + if (bus == 0) { + return ((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) | + bsf); + /* PEM otherwise */ + } else { + int pem; + + /* PEM number is equal to domain */ + pem = pci_get_domain(pci_dev); + + /* Hardcode appropriate PEM numbers */ + if (pem < 3 ) + return ((0x1 << PCI_RID_DOMAIN_SHIFT) | bsf); + + if (pem < 6 ) + return ((0x3 << PCI_RID_DOMAIN_SHIFT) | bsf); + + if (pem < 9 ) + return ((0x9 << PCI_RID_DOMAIN_SHIFT) | bsf); + + if (pem < 12 ) + return ((0xB << PCI_RID_DOMAIN_SHIFT) | bsf); + } + + return (0); +} + +static __inline uint32_t +its_get_devid_default(device_t pci_dev) +{ + + return (PCI_DEVID_GENERIC(pci_dev)); +} + +static uint32_t +its_get_devid(device_t pci_dev) +{ + struct its_quirks *quirk = &its_quirks[0]; + + while (quirk->cpuid != 0) { + if (CPU_MATCH_RAW(quirk->cpuid_mask, quirk->cpuid)) { + if (quirk->devid_func != NULL) + return ((*quirk->devid_func)(pci_dev)); + } + quirk++; + } + + return (its_get_devid_default(pci_dev)); +} + static int gic_v3_its_attach(device_t dev) { @@ -1300,7 +1385,7 @@ if (newdev != NULL) return (newdev); - devid = PCI_DEVID(pci_dev); + devid = its_get_devid(pci_dev); /* There was no previously created device. Create one now */ newdev = malloc(sizeof(*newdev), M_GIC_V3_ITS, (M_WAITOK | M_ZERO)); Index: sys/arm64/arm64/gic_v3_var.h =================================================================== --- sys/arm64/arm64/gic_v3_var.h +++ sys/arm64/arm64/gic_v3_var.h @@ -277,13 +277,14 @@ reg, val); \ }) -#define PCI_DEVID(pci_dev) \ +#define PCI_RID_DOMAIN_SHIFT 16 + +#define PCI_DEVID_GENERIC(pci_dev) \ ({ \ - (((pci_get_domain(pci_dev) >> 2) << 19) | \ - ((pci_get_domain(pci_dev) % 4) << 16) | \ - (pci_get_bus(pci_dev) << 8) | \ - (pci_get_slot(pci_dev) << 3) | \ - (pci_get_function(pci_dev) << 0)); \ + ((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) | \ + (pci_get_bus(pci_dev) << PCI_RID_BUS_SHIFT) | \ + (pci_get_slot(pci_dev) << PCI_RID_SLOT_SHIFT) | \ + (pci_get_function(pci_dev) << PCI_RID_FUNC_SHIFT)); \ }) /*