Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F167252724
D5231.id13123.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D5231.id13123.diff
View Options
Index: sys/arm64/arm64/gic_v3.c
===================================================================
--- sys/arm64/arm64/gic_v3.c
+++ sys/arm64/arm64/gic_v3.c
@@ -58,6 +58,7 @@
#include "gic_v3_var.h"
/* Device and PIC methods */
+static int gic_v3_bind(device_t, u_int, u_int);
static void gic_v3_dispatch(device_t, struct trapframe *);
static void gic_v3_eoi(device_t, u_int);
static void gic_v3_mask_irq(device_t, u_int);
@@ -72,6 +73,7 @@
DEVMETHOD(device_detach, gic_v3_detach),
/* PIC interface */
+ DEVMETHOD(pic_bind, gic_v3_bind),
DEVMETHOD(pic_dispatch, gic_v3_dispatch),
DEVMETHOD(pic_eoi, gic_v3_eoi),
DEVMETHOD(pic_mask, gic_v3_mask_irq),
@@ -244,6 +246,28 @@
/*
* PIC interface.
*/
+
+static int
+gic_v3_bind(device_t dev, u_int irq, u_int cpuid)
+{
+ uint64_t aff;
+ struct gic_v3_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (irq <= GIC_LAST_PPI) {
+ /* Can't bind PPI to another CPU but it's not an error */
+ return (0);
+ } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) {
+ aff = CPU_AFFINITY(cpuid);
+ gic_d_write(sc, 4, GICD_IROUTER(irq), aff);
+ return (0);
+ } else if (irq >= GIC_FIRST_LPI)
+ return (lpi_migrate(dev, irq, cpuid));
+
+ return (EINVAL);
+}
+
static void
gic_v3_dispatch(device_t dev, struct trapframe *frame)
{
Index: sys/arm64/arm64/gic_v3_its.c
===================================================================
--- sys/arm64/arm64/gic_v3_its.c
+++ sys/arm64/arm64/gic_v3_its.c
@@ -92,9 +92,13 @@
static void its_init_commandq(struct gic_v3_its_softc *);
static void its_init_cpu_collection(struct gic_v3_its_softc *);
static uint32_t its_get_devid(device_t);
+static struct its_dev * its_device_find_locked(struct gic_v3_its_softc *,
+ device_t, uint32_t);
static int its_cmd_send(struct gic_v3_its_softc *, struct its_cmd_desc *);
+static void its_cmd_movi(struct gic_v3_its_softc *, struct its_dev *, uint32_t,
+ struct its_col *);
static void its_cmd_mapc(struct gic_v3_its_softc *, struct its_col *, uint8_t);
static void its_cmd_mapvi(struct gic_v3_its_softc *, struct its_dev *, uint32_t,
uint32_t);
@@ -953,6 +957,32 @@
(unmask == TRUE) ? "unmask" : "mask", irq);
}
+int
+lpi_migrate(device_t parent, uint32_t irq, u_int cpuid)
+{
+ struct gic_v3_its_softc *sc;
+ struct its_dev *its_dev;
+ struct its_col *col;
+
+ sc = its_sc;
+ mtx_lock_spin(&sc->its_dev_lock);
+ its_dev = its_device_find_locked(sc, NULL, irq);
+ mtx_unlock_spin(&sc->its_dev_lock);
+ if (its_dev == NULL) {
+ /* Cannot migrate not configured LPI */
+ return (ENXIO);
+ }
+
+ /* Find local device's interrupt identifier */
+ irq = irq - its_dev->lpis.lpi_base;
+ /* Move interrupt to another collection */
+ col = sc->its_cols[cpuid];
+ its_dev->col->col_id = cpuid;
+ its_cmd_movi(sc, its_dev, irq, col);
+
+ return (0);
+}
+
void
lpi_unmask_irq(device_t parent, uint32_t irq)
{
@@ -1053,6 +1083,20 @@
}
static void
+its_cmd_movi(struct gic_v3_its_softc *sc, struct its_dev *its_dev,
+ uint32_t id, struct its_col *col)
+{
+ struct its_cmd_desc desc;
+
+ desc.cmd_type = ITS_CMD_MOVI;
+ desc.cmd_desc_movi.its_dev = its_dev;
+ desc.cmd_desc_movi.col = col;
+ desc.cmd_desc_movi.id = id;
+
+ its_cmd_send(sc, &desc);
+}
+
+static void
its_cmd_mapc(struct gic_v3_its_softc *sc, struct its_col *col, uint8_t valid)
{
struct its_cmd_desc desc;
@@ -1216,6 +1260,12 @@
target = ITS_TARGET_NONE;
switch (cmd_type) {
+ case ITS_CMD_MOVI: /* Move interrupt ID to another collection */
+ cmd_format_command(cmd, ITS_CMD_MOVI);
+ cmd_format_id(cmd, desc->cmd_desc_movi.id);
+ cmd_format_col(cmd, desc->cmd_desc_movi.its_dev->col->col_id);
+ cmd_format_devid(cmd, desc->cmd_desc_movi.its_dev->devid);
+ break;
case ITS_CMD_SYNC: /* Wait for previous commands completion */
target = desc->cmd_desc_sync.col->col_target;
cmd_format_command(cmd, ITS_CMD_SYNC);
@@ -1367,16 +1417,28 @@
return (0);
}
+/* Find ITS device descriptor by pci_dev or irq number */
static struct its_dev *
-its_device_find_locked(struct gic_v3_its_softc *sc, device_t pci_dev)
+its_device_find_locked(struct gic_v3_its_softc *sc, device_t pci_dev,
+ uint32_t irq)
{
struct its_dev *its_dev;
+ struct lpi_chunk *lpis;
mtx_assert(&sc->its_dev_lock, MA_OWNED);
+ KASSERT((pci_dev == NULL || irq == 0),
+ ("%s: Can't search by both pci_dev and irq number", __func__));
/* Find existing device if any */
TAILQ_FOREACH(its_dev, &sc->its_dev_list, entry) {
- if (its_dev->pci_dev == pci_dev)
- return (its_dev);
+ if (pci_dev != NULL) {
+ if (its_dev->pci_dev == pci_dev)
+ return (its_dev);
+ } else if (irq != 0) {
+ lpis = &its_dev->lpis;
+ if ((irq >= lpis->lpi_base) &&
+ (irq < (lpis->lpi_base + lpis->lpi_num)))
+ return (its_dev);
+ }
}
return (NULL);
@@ -1395,7 +1457,7 @@
mtx_lock_spin(&sc->its_dev_lock);
/* Find existing device if any */
- newdev = its_device_find_locked(sc, pci_dev);
+ newdev = its_device_find_locked(sc, pci_dev, 0);
mtx_unlock_spin(&sc->its_dev_lock);
if (newdev != NULL)
return (newdev);
Index: sys/arm64/arm64/gic_v3_var.h
===================================================================
--- sys/arm64/arm64/gic_v3_var.h
+++ sys/arm64/arm64/gic_v3_var.h
@@ -133,6 +133,7 @@
};
/* ITS commands encoding */
+#define ITS_CMD_MOVI (0x01)
#define ITS_CMD_SYNC (0x05)
#define ITS_CMD_MAPD (0x08)
#define ITS_CMD_MAPC (0x09)
@@ -172,6 +173,12 @@
union {
struct {
+ struct its_dev *its_dev;
+ struct its_col *col;
+ uint32_t id;
+ } cmd_desc_movi;
+
+ struct {
struct its_col *col;
} cmd_desc_sync;
@@ -257,6 +264,7 @@
int its_init_cpu(struct gic_v3_its_softc *);
+int lpi_migrate(device_t, uint32_t, u_int);
void lpi_unmask_irq(device_t, uint32_t);
void lpi_mask_irq(device_t, uint32_t);
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 21, 9:43 AM (11 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37027467
Default Alt Text
D5231.id13123.diff (5 KB)
Attached To
Mode
D5231: Support interrupts binding in GICv3 and ITS
Attached
Detach File
Event Timeline
Log In to Comment