powerpc/pic: Add a PIC_AP_INIT() to set up AP PIC info

pc_cpuid may not match the PIC's idea of a given CPU.  Since openpic
has a WHOAMI register, we can use that to get the PIC's idea of the CPU.
This needs to be done on each AP, so add a PIC_AP_INIT device method so
the PIC can perform any AP-specific initialization at AP bootstrap time.

This fixes SMP on e6500, which is still lacking SMT support.

Differential Revision:	https://reviews.freebsd.org/D56421
This commit is contained in:
Justin Hibbits
2026-04-29 20:12:18 -04:00
parent 72e2ae505c
commit 40bcad56f1
4 changed files with 26 additions and 7 deletions
+1
View File
@@ -45,6 +45,7 @@ struct pvo_entry;
struct thread *pc_vecthread; /* current vec user */ \ struct thread *pc_vecthread; /* current vec user */ \
struct thread *pc_htmthread; /* current htm user */ \ struct thread *pc_htmthread; /* current htm user */ \
uintptr_t pc_hwref; \ uintptr_t pc_hwref; \
uintptr_t pc_pic; \
int pc_bsp; \ int pc_bsp; \
volatile int pc_awake; \ volatile int pc_awake; \
uint32_t pc_ipimask; \ uint32_t pc_ipimask; \
+1
View File
@@ -87,6 +87,7 @@ machdep_ap_bootstrap(void)
/* Give platform code a chance to do anything else necessary */ /* Give platform code a chance to do anything else necessary */
platform_smp_ap_init(); platform_smp_ap_init();
PIC_AP_INIT(root_pic);
/* Initialize decrementer */ /* Initialize decrementer */
decr_ap_init(); decr_ap_init();
+21 -7
View File
@@ -254,7 +254,7 @@ openpic_bind(device_t dev, u_int irq, cpuset_t cpumask, void **priv __unused)
break; break;
ncpu++; ncpu++;
} }
mask &= (1 << cpu); mask = (1 << __pcpu[cpu].pc_pic);
} }
openpic_write(sc, OPENPIC_IDEST(irq), mask); openpic_write(sc, OPENPIC_IDEST(irq), mask);
@@ -288,9 +288,10 @@ openpic_dispatch(device_t dev, struct trapframe *tf)
CTR1(KTR_INTR, "%s: got interrupt", __func__); CTR1(KTR_INTR, "%s: got interrupt", __func__);
cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
sc = device_get_softc(dev); sc = device_get_softc(dev);
cpuid = (dev == root_pic) ? PCPU_GET(pic) : 0;
while (1) { while (1) {
vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid)); vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid));
vector &= OPENPIC_VECTOR_MASK; vector &= OPENPIC_VECTOR_MASK;
@@ -337,9 +338,9 @@ openpic_eoi(device_t dev, u_int irq __unused, void *priv __unused)
struct openpic_softc *sc; struct openpic_softc *sc;
u_int cpuid; u_int cpuid;
cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
sc = device_get_softc(dev); sc = device_get_softc(dev);
cpuid = (dev == root_pic) ? PCPU_GET(pic) : 0;
openpic_write(sc, OPENPIC_PCPU_EOI(cpuid), 0); openpic_write(sc, OPENPIC_PCPU_EOI(cpuid), 0);
} }
@@ -352,8 +353,8 @@ openpic_ipi(device_t dev, u_int cpu)
sc = device_get_softc(dev); sc = device_get_softc(dev);
sched_pin(); sched_pin();
openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0), openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(pic), 0),
1u << cpu); 1u << pcpu_find(cpu)->pc_pic);
sched_unpin(); sched_unpin();
} }
@@ -454,6 +455,18 @@ openpic_resume(device_t dev)
return (0); return (0);
} }
static void
openpic_ap_init(device_t dev)
{
struct openpic_softc *sc;
if (dev != root_pic)
return;
sc = device_get_softc(dev);
PCPU_SET(pic, bus_read_4(sc->sc_memr, OPENPIC_WHOAMI));
}
static device_method_t openpic_methods[] = { static device_method_t openpic_methods[] = {
/* Device interface */ /* Device interface */
DEVMETHOD(device_suspend, openpic_suspend), DEVMETHOD(device_suspend, openpic_suspend),
@@ -468,6 +481,7 @@ static device_method_t openpic_methods[] = {
DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_ipi, openpic_ipi),
DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_mask, openpic_mask),
DEVMETHOD(pic_unmask, openpic_unmask), DEVMETHOD(pic_unmask, openpic_unmask),
DEVMETHOD(pic_ap_init, openpic_ap_init),
DEVMETHOD_END DEVMETHOD_END
}; };
+3
View File
@@ -100,3 +100,6 @@ METHOD void unmask {
void *priv; void *priv;
}; };
METHOD void ap_init {
device_t dev;
};