Introduce ITS support for ARM64

Add ARM ITS (Interrupt Translation Services) support required
to bring-up message signalled interrupts on some ARM64 platforms.

Obtained from: Semihalf
Sponsored by:  The FreeBSD Foundation
This commit is contained in:
zbb 2015-07-06 18:27:41 +00:00
parent 88db72c33d
commit 5265baf791
7 changed files with 2073 additions and 5 deletions

View File

@ -236,19 +236,18 @@ gic_v3_dispatch(device_t dev, struct trapframe *frame)
break;
if (__predict_true((active_irq >= GIC_FIRST_PPI &&
active_irq <= GIC_LAST_SPI))) {
active_irq <= GIC_LAST_SPI) || active_irq >= GIC_FIRST_LPI)) {
arm_dispatch_intr(active_irq, frame);
continue;
}
if (active_irq <= GIC_LAST_SGI || active_irq >= GIC_FIRST_LPI) {
if (active_irq <= GIC_LAST_SGI) {
/*
* TODO: Implement proper SGI/LPI handling.
* TODO: Implement proper SGI handling.
* Mask it if such is received for some reason.
*/
device_printf(dev,
"Received unsupported interrupt type: %s\n",
active_irq >= GIC_FIRST_LPI ? "LPI" : "SGI");
"Received unsupported interrupt type: SGI\n");
PIC_MASK(dev, active_irq);
}
}
@ -275,6 +274,8 @@ gic_v3_mask_irq(device_t dev, u_int irq)
} else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
gic_r_write(sc, 4, GICD_ICENABLER(irq), GICD_I_MASK(irq));
gic_v3_wait_for_rwp(sc, DIST);
} else if (irq >= GIC_FIRST_LPI) { /* LPIs */
lpi_mask_irq(dev, irq);
} else
panic("%s: Unsupported IRQ number %u", __func__, irq);
}
@ -293,6 +294,8 @@ gic_v3_unmask_irq(device_t dev, u_int irq)
} else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
gic_d_write(sc, 4, GICD_ISENABLER(irq), GICD_I_MASK(irq));
gic_v3_wait_for_rwp(sc, DIST);
} else if (irq >= GIC_FIRST_LPI) { /* LPIs */
lpi_unmask_irq(dev, irq);
} else
panic("%s: Unsupported IRQ number %u", __func__, irq);
}

View File

@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/resource.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
@ -51,11 +53,27 @@ __FBSDID("$FreeBSD$");
static int gic_v3_fdt_probe(device_t);
static int gic_v3_fdt_attach(device_t);
static struct resource *gic_v3_ofw_bus_alloc_res(device_t, device_t, int, int *,
u_long, u_long, u_long, u_int);
static const struct ofw_bus_devinfo *gic_v3_ofw_get_devinfo(device_t, device_t);
static device_method_t gic_v3_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, gic_v3_fdt_probe),
DEVMETHOD(device_attach, gic_v3_fdt_attach),
/* Bus interface */
DEVMETHOD(bus_alloc_resource, gic_v3_ofw_bus_alloc_res),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, gic_v3_ofw_get_devinfo),
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
/* End */
DEVMETHOD_END
};
@ -70,6 +88,11 @@ EARLY_DRIVER_MODULE(gic_v3, simplebus, gic_v3_fdt_driver, gic_v3_fdt_devclass,
EARLY_DRIVER_MODULE(gic_v3, ofwbus, gic_v3_fdt_driver, gic_v3_fdt_devclass,
0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
/*
* Helper functions declarations.
*/
static int gic_v3_ofw_bus_attach(device_t);
/*
* Device interface.
*/
@ -109,6 +132,17 @@ gic_v3_fdt_attach(device_t dev)
err = gic_v3_attach(dev);
if (err)
goto error;
/*
* Try to register ITS to this GIC.
* GIC will act as a bus in that case.
* Failure here will not affect main GIC functionality.
*/
if (gic_v3_ofw_bus_attach(dev) != 0) {
if (bootverbose) {
device_printf(dev,
"Failed to attach ITS to this GIC\n");
}
}
return (err);
@ -122,3 +156,155 @@ gic_v3_fdt_attach(device_t dev)
return (err);
}
/* OFW bus interface */
struct gic_v3_ofw_devinfo {
struct ofw_bus_devinfo di_dinfo;
struct resource_list di_rl;
};
static const struct ofw_bus_devinfo *
gic_v3_ofw_get_devinfo(device_t bus __unused, device_t child)
{
struct gic_v3_ofw_devinfo *di;
di = device_get_ivars(child);
return (&di->di_dinfo);
}
static struct resource *
gic_v3_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct gic_v3_ofw_devinfo *di;
struct resource_list_entry *rle;
int ranges_len;
if ((start == 0UL) && (end == ~0UL)) {
if ((di = device_get_ivars(child)) == NULL)
return (NULL);
if (type != SYS_RES_MEMORY)
return (NULL);
/* Find defaults for this rid */
rle = resource_list_find(&di->di_rl, type, *rid);
if (rle == NULL)
return (NULL);
start = rle->start;
end = rle->end;
count = rle->count;
}
/*
* XXX: No ranges remap!
* Absolute address is expected.
*/
if (ofw_bus_has_prop(bus, "ranges")) {
ranges_len = OF_getproplen(ofw_bus_get_node(bus), "ranges");
if (ranges_len != 0) {
if (bootverbose) {
device_printf(child,
"Ranges remap not supported\n");
}
return (NULL);
}
}
return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
count, flags));
}
/* Helper functions */
/*
* Bus capability support for GICv3.
* Collects and configures device informations and finally
* adds ITS device as a child of GICv3 in Newbus hierarchy.
*/
static int
gic_v3_ofw_bus_attach(device_t dev)
{
struct gic_v3_ofw_devinfo *di;
device_t child;
phandle_t parent, node;
pcell_t addr_cells, size_cells;
parent = ofw_bus_get_node(dev);
if (parent > 0) {
addr_cells = 2;
OF_getencprop(parent, "#address-cells", &addr_cells,
sizeof(addr_cells));
size_cells = 2;
OF_getencprop(parent, "#size-cells", &size_cells,
sizeof(size_cells));
/* Iterate through all GIC subordinates */
for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
/* Allocate and populate devinfo. */
di = malloc(sizeof(*di), M_GIC_V3, M_WAITOK | M_ZERO);
if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node)) {
if (bootverbose) {
device_printf(dev,
"Could not set up devinfo for ITS\n");
}
free(di, M_GIC_V3);
continue;
}
/* Initialize and populate resource list. */
resource_list_init(&di->di_rl);
ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
&di->di_rl);
/* Should not have any interrupts, so don't add any */
/* Add newbus device for this FDT node */
child = device_add_child(dev, NULL, -1);
if (!child) {
if (bootverbose) {
device_printf(dev,
"Could not add child: %s\n",
di->di_dinfo.obd_name);
}
resource_list_free(&di->di_rl);
ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
free(di, M_GIC_V3);
continue;
}
device_set_ivars(child, di);
}
}
return (bus_generic_attach(dev));
}
static int gic_v3_its_fdt_probe(device_t dev);
static device_method_t gic_v3_its_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, gic_v3_its_fdt_probe),
/* End */
DEVMETHOD_END
};
DEFINE_CLASS_1(gic_v3_its, gic_v3_its_fdt_driver, gic_v3_its_fdt_methods,
sizeof(struct gic_v3_its_softc), gic_v3_its_driver);
static devclass_t gic_v3_its_fdt_devclass;
EARLY_DRIVER_MODULE(gic_v3_its, gic_v3, gic_v3_its_fdt_driver,
gic_v3_its_fdt_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
static int
gic_v3_its_fdt_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, GIC_V3_ITS_COMPSTR))
return (ENXIO);
device_set_desc(dev, GIC_V3_ITS_DEVSTR);
return (BUS_PROBE_DEFAULT);
}

1448
sys/arm64/arm64/gic_v3_its.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -101,17 +101,100 @@
#define GICR_PIDR2_ARCH_GICv4 (0x40)
/* Redistributor registers */
#define GICR_CTLR GICD_CTLR
#define GICR_CTLR_LPI_ENABLE (1 << 0)
#define GICR_PIDR2 GICD_PIDR2
#define GICR_TYPER (0x0008)
#define GICR_TYPER_PLPIS (1 << 0)
#define GICR_TYPER_VLPIS (1 << 1)
#define GICR_TYPER_LAST (1 << 4)
#define GICR_TYPER_CPUNUM_SHIFT (8)
#define GICR_TYPER_CPUNUM_MASK (0xFFFUL << GICR_TYPER_CPUNUM_SHIFT)
#define GICR_TYPER_CPUNUM(x) \
(((x) & GICR_TYPER_CPUNUM_MASK) >> GICR_TYPER_CPUNUM_SHIFT)
#define GICR_TYPER_AFF_SHIFT (32)
#define GICR_WAKER (0x0014)
#define GICR_WAKER_PS (1 << 1) /* Processor sleep */
#define GICR_WAKER_CA (1 << 2) /* Children asleep */
#define GICR_PROPBASER (0x0070)
#define GICR_PROPBASER_IDBITS_MASK 0x1FUL
/*
* Cacheability
* 0x0 - Device-nGnRnE
* 0x1 - Normal Inner Non-cacheable
* 0x2 - Normal Inner Read-allocate, Write-through
* 0x3 - Normal Inner Read-allocate, Write-back
* 0x4 - Normal Inner Write-allocate, Write-through
* 0x5 - Normal Inner Write-allocate, Write-back
* 0x6 - Normal Inner Read-allocate, Write-allocate, Write-through
* 0x7 - Normal Inner Read-allocate, Write-allocate, Write-back
*/
#define GICR_PROPBASER_CACHE_SHIFT 7
#define GICR_PROPBASER_CACHE_DnGnRnE 0x0UL
#define GICR_PROPBASER_CACHE_NIN 0x1UL
#define GICR_PROPBASER_CACHE_NIRAWT 0x2UL
#define GICR_PROPBASER_CACHE_NIRAWB 0x3UL
#define GICR_PROPBASER_CACHE_NIWAWT 0x4UL
#define GICR_PROPBASER_CACHE_NIWAWB 0x5UL
#define GICR_PROPBASER_CACHE_NIRAWAWT 0x6UL
#define GICR_PROPBASER_CACHE_NIRAWAWB 0x7UL
/*
* Shareability
* 0x0 - Non-shareable
* 0x1 - Inner-shareable
* 0x2 - Outer-shareable
* 0x3 - Reserved. Threated as 0x0
*/
#define GICR_PROPBASER_SHARE_SHIFT 10
#define GICR_PROPBASER_SHARE_NS 0x0UL
#define GICR_PROPBASER_SHARE_IS 0x1UL
#define GICR_PROPBASER_SHARE_OS 0x2UL
#define GICR_PROPBASER_SHARE_RES 0x3UL
#define GICR_PROPBASER_SHARE_MASK \
(0x3UL << GICR_PROPBASER_SHARE_SHIFT)
#define GICR_PENDBASER (0x0078)
/*
* Cacheability
* 0x0 - Device-nGnRnE
* 0x1 - Normal Inner Non-cacheable
* 0x2 - Normal Inner Read-allocate, Write-through
* 0x3 - Normal Inner Read-allocate, Write-back
* 0x4 - Normal Inner Write-allocate, Write-through
* 0x5 - Normal Inner Write-allocate, Write-back
* 0x6 - Normal Inner Read-allocate, Write-allocate, Write-through
* 0x7 - Normal Inner Read-allocate, Write-allocate, Write-back
*/
#define GICR_PENDBASER_CACHE_SHIFT 7
#define GICR_PENDBASER_CACHE_DnGnRnE 0x0UL
#define GICR_PENDBASER_CACHE_NIN 0x1UL
#define GICR_PENDBASER_CACHE_NIRAWT 0x2UL
#define GICR_PENDBASER_CACHE_NIRAWB 0x3UL
#define GICR_PENDBASER_CACHE_NIWAWT 0x4UL
#define GICR_PENDBASER_CACHE_NIWAWB 0x5UL
#define GICR_PENDBASER_CACHE_NIRAWAWT 0x6UL
#define GICR_PENDBASER_CACHE_NIRAWAWB 0x7UL
/*
* Shareability
* 0x0 - Non-shareable
* 0x1 - Inner-shareable
* 0x2 - Outer-shareable
* 0x3 - Reserved. Threated as 0x0
*/
#define GICR_PENDBASER_SHARE_SHIFT 10
#define GICR_PENDBASER_SHARE_NS 0x0UL
#define GICR_PENDBASER_SHARE_IS 0x1UL
#define GICR_PENDBASER_SHARE_OS 0x2UL
#define GICR_PENDBASER_SHARE_RES 0x3UL
#define GICR_PENDBASER_SHARE_MASK \
(0x3UL << GICR_PENDBASER_SHARE_SHIFT)
/* Re-distributor registers for SGIs and PPIs */
#define GICR_RD_BASE_SIZE PAGE_SIZE_64K
#define GICR_SGI_BASE_SIZE PAGE_SIZE_64K
@ -125,6 +208,151 @@
#define GICR_I_PER_IPRIORITYn (GICD_I_PER_IPRIORITYn)
/* ITS registers */
#define GITS_PIDR2 GICR_PIDR2
#define GITS_PIDR2_ARCH_MASK GICR_PIDR2_ARCH_MASK
#define GITS_PIDR2_ARCH_GICv3 GICR_PIDR2_ARCH_GICv3
#define GITS_PIDR2_ARCH_GICv4 GICR_PIDR2_ARCH_GICv4
#define GITS_CTLR (0x0000)
#define GITS_CTLR_EN (1 << 0)
#define GITS_CBASER (0x0080)
#define GITS_CBASER_VALID (1UL << 63)
/*
* Cacheability
* 0x0 - Device-nGnRnE
* 0x1 - Normal Inner Non-cacheable
* 0x2 - Normal Inner Read-allocate, Write-through
* 0x3 - Normal Inner Read-allocate, Write-back
* 0x4 - Normal Inner Write-allocate, Write-through
* 0x5 - Normal Inner Write-allocate, Write-back
* 0x6 - Normal Inner Read-allocate, Write-allocate, Write-through
* 0x7 - Normal Inner Read-allocate, Write-allocate, Write-back
*/
#define GITS_CBASER_CACHE_SHIFT 59
#define GITS_CBASER_CACHE_DnGnRnE 0x0UL
#define GITS_CBASER_CACHE_NIN 0x1UL
#define GITS_CBASER_CACHE_NIRAWT 0x2UL
#define GITS_CBASER_CACHE_NIRAWB 0x3UL
#define GITS_CBASER_CACHE_NIWAWT 0x4UL
#define GITS_CBASER_CACHE_NIWAWB 0x5UL
#define GITS_CBASER_CACHE_NIRAWAWT 0x6UL
#define GITS_CBASER_CACHE_NIRAWAWB 0x7UL
#define GITS_CBASER_CACHE_MASK (0x7UL << GITS_CBASER_TYPE_SHIFT)
/*
* Shareability
* 0x0 - Non-shareable
* 0x1 - Inner-shareable
* 0x2 - Outer-shareable
* 0x3 - Reserved. Threated as 0x0
*/
#define GITS_CBASER_SHARE_SHIFT 10
#define GITS_CBASER_SHARE_NS 0x0UL
#define GITS_CBASER_SHARE_IS 0x1UL
#define GITS_CBASER_SHARE_OS 0x2UL
#define GITS_CBASER_SHARE_RES 0x3UL
#define GITS_CBASER_SHARE_MASK \
(0x3UL << GITS_CBASER_SHARE_SHIFT)
#define GITS_CBASER_PA_SHIFT 12
#define GITS_CBASER_PA_MASK (0xFFFFFFFFFUL << GITS_CBASER_PA_SHIFT)
#define GITS_CWRITER (0x0088)
#define GITS_CREADR (0x0090)
#define GITS_BASER_BASE (0x0100)
#define GITS_BASER(x) (GITS_BASER_BASE + (x) * 8)
#define GITS_BASER_VALID (1UL << 63)
#define GITS_BASER_TYPE_SHIFT 56
#define GITS_BASER_TYPE(x) \
(((x) & GITS_BASER_TYPE_MASK) >> GITS_BASER_TYPE_SHIFT)
#define GITS_BASER_TYPE_UNIMPL 0x0UL /* Unimplemented */
#define GITS_BASER_TYPE_DEV 0x1UL /* Devices */
#define GITS_BASER_TYPE_VP 0x2UL /* Virtual Processors */
#define GITS_BASER_TYPE_PP 0x3UL /* Physical Processors */
#define GITS_BASER_TYPE_IC 0x4UL /* Interrupt Collections */
#define GITS_BASER_TYPE_RES5 0x5UL /* Reserved */
#define GITS_BASER_TYPE_RES6 0x6UL /* Reserved */
#define GITS_BASER_TYPE_RES7 0x7UL /* Reserved */
#define GITS_BASER_TYPE_MASK (0x7UL << GITS_BASER_TYPE_SHIFT)
/*
* Cacheability
* 0x0 - Non-cacheable, non-bufferable
* 0x1 - Non-cacheable
* 0x2 - Read-allocate, Write-through
* 0x3 - Read-allocate, Write-back
* 0x4 - Write-allocate, Write-through
* 0x5 - Write-allocate, Write-back
* 0x6 - Read-allocate, Write-allocate, Write-through
* 0x7 - Read-allocate, Write-allocate, Write-back
*/
#define GITS_BASER_CACHE_SHIFT 59
#define GITS_BASER_CACHE_NCNB 0x0UL
#define GITS_BASER_CACHE_NC 0x1UL
#define GITS_BASER_CACHE_RAWT 0x2UL
#define GITS_BASER_CACHE_RAWB 0x3UL
#define GITS_BASER_CACHE_WAWT 0x4UL
#define GITS_BASER_CACHE_WAWB 0x5UL
#define GITS_BASER_CACHE_RAWAWT 0x6UL
#define GITS_BASER_CACHE_RAWAWB 0x7UL
#define GITS_BASER_CACHE_MASK (0x7UL << GITS_BASER_CACHE_SHIFT)
#define GITS_BASER_ESIZE_SHIFT 48
#define GITS_BASER_ESIZE_MASK (0x1FUL << GITS_BASER_ESIZE_SHIFT)
#define GITS_BASER_ESIZE(x) \
((((x) & GITS_BASER_ESIZE_MASK) >> GITS_BASER_ESIZE_SHIFT) + 1)
#define GITS_BASER_PA_SHIFT 12
#define GITS_BASER_PA_MASK (0xFFFFFFFFFUL << GITS_BASER_PA_SHIFT)
/*
* Shareability
* 0x0 - Non-shareable
* 0x1 - Inner-shareable
* 0x2 - Outer-shareable
* 0x3 - Reserved. Threated as 0x0
*/
#define GITS_BASER_SHARE_SHIFT 10
#define GITS_BASER_SHARE_NS 0x0UL
#define GITS_BASER_SHARE_IS 0x1UL
#define GITS_BASER_SHARE_OS 0x2UL
#define GITS_BASER_SHARE_RES 0x3UL
#define GITS_BASER_SHARE_MASK (0x3UL << GITS_BASER_SHARE_SHIFT)
#define GITS_BASER_PSZ_SHIFT 8
#define GITS_BASER_PSZ_4K 0x0UL
#define GITS_BASER_PSZ_16K 0x1UL
#define GITS_BASER_PSZ_64K 0x2UL
#define GITS_BASER_PSZ_MASK (0x3UL << GITS_BASER_PSZ_SHIFT)
#define GITS_BASER_SIZE_MASK 0xFFUL
#define GITS_BASER_NUM 8
#define GITS_TYPER (0x0008)
#define GITS_TYPER_PTA (1UL << 19)
#define GITS_TYPER_DEVB_SHIFT 13
#define GITS_TYPER_DEVB_MASK (0x1FUL << GITS_TYPER_DEVB_SHIFT)
/* Number of device identifiers implemented */
#define GITS_TYPER_DEVB(x) \
((((x) & GITS_TYPER_DEVB_MASK) >> GITS_TYPER_DEVB_SHIFT) + 1)
#define GITS_TYPER_ITTES_SHIFT 4
#define GITS_TYPER_ITTES_MASK (0xFUL << GITS_TYPER_ITTES_SHIFT)
/* Number of bytes per ITT Entry */
#define GITS_TYPER_ITTES(x) \
((((x) & GITS_TYPER_ITTES_MASK) >> GITS_TYPER_ITTES_SHIFT) + 1)
#define GITS_TRANSLATER (0x10040)
/*
* LPI related
*/
#define LPI_CONF_PRIO_MASK (0xFC)
#define LPI_CONF_GROUP1 (1 << 1)
#define LPI_CONF_ENABLE (1 << 0)
/*
* CPU interface
*/

View File

@ -36,6 +36,17 @@
DECLARE_CLASS(gic_v3_driver);
#define LPI_FLAGS_CONF_FLUSH (1UL << 0)
#define LPI_CONFTAB_SIZE PAGE_SIZE_64K
/* 1 bit per LPI + 1 KB more for the obligatory PPI, SGI, SPI stuff */
#define LPI_PENDTAB_SIZE ((LPI_CONFTAB_SIZE / 8) + 0x400)
struct redist_lpis {
vm_offset_t conf_base;
vm_offset_t pend_base[MAXCPU];
uint64_t flags;
};
struct gic_redists {
/*
* Re-Distributor region description.
@ -47,6 +58,8 @@ struct gic_redists {
u_int nregions;
/* Per-CPU Re-Distributor handler */
struct resource * pcpu[MAXCPU];
/* LPIs data */
struct redist_lpis lpis;
};
struct gic_v3_softc {
@ -70,6 +83,167 @@ MALLOC_DECLARE(M_GIC_V3);
int gic_v3_attach(device_t dev);
int gic_v3_detach(device_t dev);
/*
* ITS
*/
#define GIC_V3_ITS_DEVSTR "ARM GIC Interrupt Translation Service"
#define GIC_V3_ITS_COMPSTR "arm,gic-v3-its"
DECLARE_CLASS(gic_v3_its_driver);
/* LPI chunk owned by ITS device */
struct lpi_chunk {
u_int lpi_base;
u_int lpi_num;
u_int lpi_free; /* First free LPI in set */
};
/* ITS device */
struct its_dev {
TAILQ_ENTRY(its_dev) entry;
/* PCI device */
device_t pci_dev;
/* Device ID (i.e. PCI device ID) */
uint32_t devid;
/* List of assigned LPIs */
struct lpi_chunk lpis;
/* Virtual address of ITT */
vm_offset_t itt;
/* Interrupt collection */
struct its_col * col;
};
TAILQ_HEAD(its_dev_list, its_dev);
/* ITS private table description */
struct its_ptab {
vm_offset_t ptab_vaddr; /* Virtual Address of table */
size_t ptab_pgsz; /* Page size */
size_t ptab_npages; /* Number of pages */
};
/* ITS collection description. */
struct its_col {
uint64_t col_target; /* Target Re-Distributor */
uint64_t col_id; /* Collection ID */
};
/* ITS command. Each command is 32 bytes long */
struct its_cmd {
uint64_t cmd_dword[4]; /* ITS command double word */
};
/* ITS commands encoding */
#define ITS_CMD_SYNC (0x05)
#define ITS_CMD_MAPD (0x08)
#define ITS_CMD_MAPC (0x09)
#define ITS_CMD_MAPVI (0x0a)
#define ITS_CMD_MAPI (0x0b)
#define ITS_CMD_INV (0x0c)
#define ITS_CMD_INVALL (0x0d)
/* Command */
#define CMD_COMMAND_MASK (0xFFUL)
/* PCI device ID */
#define CMD_DEVID_SHIFT (32)
#define CMD_DEVID_MASK (0xFFFFFFFFUL << CMD_DEVID_SHIFT)
/* Size of IRQ ID bitfield */
#define CMD_SIZE_MASK (0xFFUL)
/* Virtual LPI ID */
#define CMD_ID_MASK (0xFFFFFFFFUL)
/* Physical LPI ID */
#define CMD_PID_SHIFT (32)
#define CMD_PID_MASK (0xFFFFFFFFUL << CMD_PID_SHIFT)
/* Collection */
#define CMD_COL_MASK (0xFFFFUL)
/* Target (CPU or Re-Distributor) */
#define CMD_TARGET_SHIFT (16)
#define CMD_TARGET_MASK (0xFFFFFFFFUL << CMD_TARGET_SHIFT)
/* Interrupt Translation Table address */
#define CMD_ITT_MASK (0xFFFFFFFFFF00UL)
/* Valid command bit */
#define CMD_VALID_SHIFT (63)
#define CMD_VALID_MASK (1UL << CMD_VALID_SHIFT)
/*
* ITS command descriptor.
* Idea for command description passing taken from Linux.
*/
struct its_cmd_desc {
uint8_t cmd_type;
union {
struct {
struct its_col *col;
} cmd_desc_sync;
struct {
struct its_col *col;
uint8_t valid;
} cmd_desc_mapc;
struct {
struct its_dev *its_dev;
uint32_t pid;
uint32_t id;
} cmd_desc_mapvi;
struct {
struct its_dev *its_dev;
uint32_t lpinum;
} cmd_desc_mapi;
struct {
struct its_dev *its_dev;
uint8_t valid;
} cmd_desc_mapd;
struct {
struct its_dev *its_dev;
uint32_t lpinum;
} cmd_desc_inv;
struct {
struct its_col *col;
} cmd_desc_invall;
};
};
#define ITS_CMDQ_SIZE PAGE_SIZE_64K
#define ITS_CMDQ_NENTRIES (ITS_CMDQ_SIZE / sizeof(struct its_cmd))
#define ITS_FLAGS_CMDQ_FLUSH (1UL << 0)
#define ITS_TARGET_NONE 0xFBADBEEF
struct gic_v3_its_softc {
device_t dev;
struct resource * its_res;
struct its_cmd * its_cmdq_base; /* ITS command queue base */
struct its_cmd * its_cmdq_write; /* ITS command queue write ptr */
struct its_ptab its_ptabs[GITS_BASER_NUM];/* ITS private tables */
struct its_col * its_cols; /* Per-CPU collections */
uint64_t its_flags;
struct its_dev_list its_dev_list;
unsigned long * its_lpi_bitmap;
uint32_t its_lpi_maxid;
struct mtx its_mtx;
struct mtx its_spin_mtx;
};
extern devclass_t gic_v3_its_devclass;
int gic_v3_its_detach(device_t);
int gic_v3_its_alloc_msix(device_t, device_t, int *);
int gic_v3_its_alloc_msi(device_t, device_t, int, int *);
int gic_v3_its_map_msix(device_t, device_t, int, uint64_t *, uint32_t *);
void lpi_unmask_irq(device_t, uint32_t);
void lpi_mask_irq(device_t, uint32_t);
/*
* GIC Distributor accessors.
* Notice that only GIC sofc can be passed.
@ -103,4 +277,28 @@ int gic_v3_detach(device_t dev);
reg, val); \
})
#define PCI_DEVID(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)); \
})
/*
* Request number of maximum MSI-X vectors for this device.
* Device can ask for less vectors than maximum supported but not more.
*/
#define PCI_MSIX_NUM(pci_dev) \
({ \
struct pci_devinfo *dinfo; \
pcicfgregs *cfg; \
\
dinfo = device_get_ivars(pci_dev); \
cfg = &dinfo->cfg; \
\
cfg->msix.msix_msgnum; \
})
#endif /* _GIC_V3_VAR_H_ */

View File

@ -82,6 +82,10 @@
#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */
#define PAGE_MASK (PAGE_SIZE - 1)
#define PAGE_SHIFT_16K 14
#define PAGE_SIZE_16K (1 << PAGE_SHIFT_16K)
#define PAGE_MASK_16K (PAGE_SIZE_16K - 1)
#define PAGE_SHIFT_64K 16
#define PAGE_SIZE_64K (1 << PAGE_SHIFT_64K)
#define PAGE_MASK_64K (PAGE_SIZE_64K - 1)

View File

@ -27,6 +27,7 @@ arm64/arm64/gic_acpi.c optional acpi
arm64/arm64/gic_fdt.c optional fdt
arm64/arm64/gic_v3.c standard
arm64/arm64/gic_v3_fdt.c optional fdt
arm64/arm64/gic_v3_its.c standard
arm64/arm64/identcpu.c standard
arm64/arm64/intr_machdep.c standard
arm64/arm64/in_cksum.c optional inet | inet6