Skip to content

Commit

Permalink
WIP: Multiple roots fo interrupt types
Browse files Browse the repository at this point in the history
  • Loading branch information
strejda committed Sep 14, 2023
1 parent 21fa097 commit 396c0b2
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 33 deletions.
23 changes: 21 additions & 2 deletions sys/arm64/arm64/gic_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,8 @@ gic_v3_alloc_resource(device_t bus, device_t child, int type, int *rid,
count, flags));
}

int
arm_gic_v3_intr(void *arg)
static int
arm_gic_v3_intr(void *arg, uint32_t type)
{
struct gic_v3_softc *sc = arg;
struct gic_v3_irqsrc *gi;
Expand Down Expand Up @@ -654,6 +654,25 @@ arm_gic_v3_intr(void *arg)
}
}

// This is only example - I think that FIQ needs slightly different handler
int
arm_gic_v3_intr_irq(void *arg)
{
struct gic_v3_softc *sc = arg;

return(arm_gic_v3_intr(sc, INTR_TYPE_IRQ));
}

int
arm_gic_v3_intr_fiq(void *arg)
{
struct gic_v3_softc *sc = arg;

panic("FIQ is not implemented yet");
return(arm_gic_v3_intr(sc, INTR_TYPE_FIQ));
}


#ifdef FDT
static int
gic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
Expand Down
10 changes: 7 additions & 3 deletions sys/arm64/arm64/gic_v3_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,16 @@ gic_v3_acpi_attach(device_t dev)
}
}

if (intr_pic_claim_root(dev, ACPI_INTR_XREF, arm_gic_v3_intr, sc,
GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
if (intr_pic_claim_root_type(dev, ACPI_INTR_XREF, arm_gic_v3_intr_irq,
sc, GIC_LAST_SGI - GIC_FIRST_SGI + 1, INTR_TYPE_IRQ) != 0) {
err = ENXIO;
goto error;
}
if (intr_pic_claim_root_type(dev, ACPI_INTR_XREF, arm_gic_v3_intr_fiq,
sc, 0, INTR_TYPE_FIQ) != 0) {
err = ENXIO;
goto error;
}

/*
* Try to register the ITS driver to this GIC. The GIC will act as
* a bus in that case. Failure here will not affect the main GIC
Expand Down
9 changes: 7 additions & 2 deletions sys/arm64/arm64/gic_v3_fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,13 @@ gic_v3_fdt_attach(device_t dev)
/* Register xref */
OF_device_register_xref(xref, dev);

if (intr_pic_claim_root(dev, xref, arm_gic_v3_intr, sc,
GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
if (intr_pic_claim_root_type(dev, xref, arm_gic_v3_intr_irq, sc,
GIC_LAST_SGI - GIC_FIRST_SGI + 1, INTR_TYPE_IRQ) != 0) {
err = ENXIO;
goto error;
}
if (intr_pic_claim_root_type(dev, xref, arm_gic_v3_intr_fiq, sc,
0, INTR_TYPE_FIQ) != 0) {
err = ENXIO;
goto error;
}
Expand Down
10 changes: 5 additions & 5 deletions sys/arm64/arm64/mp_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,15 +330,15 @@ static void
pic_ipi_send(void *arg, cpuset_t cpus, u_int ipi)
{

KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
KASSERT(intr_irq_root_dev[0] != NULL, ("%s: no root attached", __func__));

/*
* Ensure that this CPU's stores will be visible to IPI
* recipients before starting to send the interrupts.
*/
dsb(ishst);

PIC_IPI_SEND(intr_irq_root_dev, arg, cpus, ipi);
PIC_IPI_SEND(intr_irq_root_dev[0], arg, cpus, ipi);
}

/*
Expand All @@ -354,10 +354,10 @@ intr_pic_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand,
struct intr_ipi *ii;
int error;

KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
KASSERT(intr_irq_root_dev[0] != NULL, ("%s: no root attached", __func__));
KASSERT(hand != NULL, ("%s: ipi %u no handler", __func__, ipi));

error = PIC_IPI_SETUP(intr_irq_root_dev, ipi, &isrc);
error = PIC_IPI_SETUP(intr_irq_root_dev[0], ipi, &isrc);
if (error != 0)
return;

Expand All @@ -373,7 +373,7 @@ intr_pic_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand,
strlcpy(ii->ii_name, name, INTR_IPI_NAMELEN);
ii->ii_count = intr_ipi_setup_counters(name);

PIC_ENABLE_INTR(intr_irq_root_dev, isrc);
PIC_ENABLE_INTR(intr_irq_root_dev[0], isrc);
}

static void
Expand Down
69 changes: 49 additions & 20 deletions sys/kern/subr_intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ __FBSDID("$FreeBSD$");
#include "msi_if.h"

#define INTRNAME_LEN (2*MAXCOMLEN + 1)

#define INTR_TYPE_MAX 2
#ifdef DEBUG
#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
printf(fmt,##args); } while (0)
Expand All @@ -96,13 +96,14 @@ MALLOC_DECLARE(M_INTRNG);
MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling");

/* Main interrupt handler called from assembler -> 'hidden' for C code. */
void intr_irq_handler_type(struct trapframe *tf, uint32_t);
void intr_irq_handler(struct trapframe *tf);

/* Root interrupt controller stuff. */
device_t intr_irq_root_dev;
static intr_irq_filter_t *irq_root_filter;
static void *irq_root_arg;
static u_int irq_root_ipicount;
/* Root interrupt controller array stuff. */
device_t intr_irq_root_dev[INTR_TYPE_MAX + 1];
static intr_irq_filter_t *irq_root_filter[INTR_TYPE_MAX + 1];
static void *irq_root_arg[INTR_TYPE_MAX + 1];
static u_int irq_root_ipicount[INTR_TYPE_MAX + 1];

struct intr_pic_child {
SLIST_ENTRY(intr_pic_child) pc_next;
Expand Down Expand Up @@ -339,21 +340,22 @@ intr_ipi_setup_counters(const char *name)
* from the assembler, where CPU interrupt is served.
*/
void
intr_irq_handler(struct trapframe *tf)
intr_irq_handler_type(struct trapframe *tf, uint32_t type)
{
struct trapframe * oldframe;
struct thread * td;

KASSERT(irq_root_filter != NULL, ("%s: no filter", __func__));
KASSERT(irq_root_filter[type] != NULL, ("%s: no filter", __func__));

kasan_mark(tf, sizeof(*tf), sizeof(*tf), 0);

VM_CNT_INC(v_intr);
// ??? Is critical enter valid for all interrupt types,mainly NMI ???
critical_enter();
td = curthread;
oldframe = td->td_intr_frame;
td->td_intr_frame = tf;
irq_root_filter(irq_root_arg);
irq_root_filter[type](irq_root_arg[type]);
td->td_intr_frame = oldframe;
critical_exit();
#ifdef HWPMC_HOOKS
Expand All @@ -363,6 +365,15 @@ intr_irq_handler(struct trapframe *tf)
#endif
}

// remove me after all MD parts was converted
void
intr_irq_handler(struct trapframe *tf)
{

intr_irq_handler_type(tf, INTR_TYPE_IRQ);
}


int
intr_child_irq_handler(struct intr_pic *parent, uintptr_t irq)
{
Expand Down Expand Up @@ -885,8 +896,8 @@ intr_pic_deregister(device_t dev, intptr_t xref)
* an interrupts property and thus no explicit interrupt parent."
*/
int
intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
void *arg, u_int ipicount)
intr_pic_claim_root_type(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
void *arg, u_int ipicount, uint32_t type)
{
struct intr_pic *pic;

Expand All @@ -910,20 +921,36 @@ intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
* Note that we further suppose that there is not threaded interrupt
* routine (handler) on the root. See intr_irq_handler().
*/
if (intr_irq_root_dev != NULL) {
if (intr_irq_root_dev[type] != NULL) {
device_printf(dev, "another root already set\n");
return (EBUSY);
}
intr_irq_root_dev[type] = dev;
#if 1 // Remove/modfy me after D35899 will be committed
if (intr_irq_root_dev[0] != 0 && intr_irq_root_dev[0] != dev)
panic ("All interrupt roots must be connected to same device");
intr_irq_root_dev[0] = dev;
#endif

intr_irq_root_dev = dev;
irq_root_filter = filter;
irq_root_arg = arg;
irq_root_ipicount = ipicount;
irq_root_filter[type] = filter;
irq_root_arg[type] = arg;
irq_root_ipicount[type] = ipicount;

debugf("irq root set to %s\n", device_get_nameunit(dev));
debugf("irq root[%ju] set to %s\n", (uintmax_t)type,
device_get_nameunit(dev));
return (0);
}

int
intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
void *arg, u_int ipicount)
{
int error;

error = intr_pic_claim_root_type(dev, xref, filter, arg, ipicount,
INTR_TYPE_IRQ);
return (error);
}
/*
* Add a handler to manage a sub range of a parents interrupts.
*/
Expand Down Expand Up @@ -1562,14 +1589,16 @@ dosoftints(void)
void
intr_pic_init_secondary(void)
{

/*
* QQQ: Only root PIC is aware of other CPUs ???
*/
KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
KASSERT(intr_irq_root_dev[0] != NULL, ("%s: no IRQ root attached", __func__));

//mtx_lock(&isrc_table_lock);
PIC_INIT_SECONDARY(intr_irq_root_dev);
//for (uint32_t i = 0; i < INTR_TYPE_MAX; i++)
// PIC_INIT_SECONDARY(intr_irq_root_dev[i]);
PIC_INIT_SECONDARY(intr_irq_root_dev[0]);
//mtx_unlock(&isrc_table_lock);
}
#endif
Expand Down
10 changes: 9 additions & 1 deletion sys/sys/intr.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@

#include <sys/systm.h>

#define INTR_TYPE_IRQ 0
#define INTR_TYPE_FIQ 1
#define INTR_TYPE_NMI 2


#define INTR_IRQ_INVALID 0xFFFFFFFF

enum intr_map_data_type {
Expand Down Expand Up @@ -96,6 +101,7 @@ struct intr_irqsrc {
#endif
/* Used by MSI interrupts to store the iommu details */
void * isrc_iommu;
uint32_t isdrc_intr_type; // Fill it !!!
};

/* Intr interface for PIC. */
Expand All @@ -113,11 +119,13 @@ u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
struct intr_pic *intr_pic_register(device_t, intptr_t);
int intr_pic_deregister(device_t, intptr_t);
int intr_pic_claim_root(device_t, intptr_t, intr_irq_filter_t *, void *, u_int);
int intr_pic_claim_root_type(device_t, intptr_t, intr_irq_filter_t *, void *,
u_int, uint32_t);
int intr_pic_add_handler(device_t, struct intr_pic *,
intr_child_irq_filter_t *, void *, uintptr_t, uintptr_t);
bool intr_is_per_cpu(struct resource *);

extern device_t intr_irq_root_dev;
extern device_t intr_irq_root_dev[];

/* Intr interface for BUS. */

Expand Down

0 comments on commit 396c0b2

Please sign in to comment.