aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2008-04-27 22:33:43 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2008-04-27 22:33:43 +0000
commit12640815f815936a684029de569522738d5b22da (patch)
tree4b070e2f496ebbb1c51a6e269f603b5beaaa4f8a /sys
parent7de3bc26a57277bf49faa8cb11ae591663068c6f (diff)
downloadsrc-12640815f815936a684029de569522738d5b22da.tar.gz
src-12640815f815936a684029de569522738d5b22da.zip
MFp4: SMP support
Notes
Notes: svn path=/head/; revision=178628
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files.powerpc1
-rw-r--r--sys/powerpc/aim/clock.c40
-rw-r--r--sys/powerpc/aim/locore.S10
-rw-r--r--sys/powerpc/aim/machdep.c15
-rw-r--r--sys/powerpc/aim/mmu_oea.c82
-rw-r--r--sys/powerpc/aim/mp_cpudep.c231
-rw-r--r--sys/powerpc/aim/swtch.S14
-rw-r--r--sys/powerpc/aim/trap_subr.S71
-rw-r--r--sys/powerpc/aim/vm_machdep.c9
-rw-r--r--sys/powerpc/booke/trap_subr.S4
-rw-r--r--sys/powerpc/conf/NOTES2
-rw-r--r--sys/powerpc/include/cpufunc.h10
-rw-r--r--sys/powerpc/include/pcpu.h15
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c29
-rw-r--r--sys/powerpc/powerpc/mp_machdep.c297
-rw-r--r--sys/powerpc/powerpc/openpic.c22
16 files changed, 715 insertions, 137 deletions
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 150858208a9f..1cb0bb69f9c6 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -68,6 +68,7 @@ powerpc/aim/interrupt.c optional aim
powerpc/aim/locore.S optional aim no-obj
powerpc/aim/machdep.c optional aim
powerpc/aim/mmu_oea.c optional aim
+powerpc/aim/mp_cpudep.c optional aim smp
powerpc/aim/nexus.c optional aim
powerpc/aim/ofw_machdep.c optional aim
powerpc/aim/ofwmagic.S optional aim
diff --git a/sys/powerpc/aim/clock.c b/sys/powerpc/aim/clock.c
index 1911220dfbad..34c00c8da6f1 100644
--- a/sys/powerpc/aim/clock.c
+++ b/sys/powerpc/aim/clock.c
@@ -61,10 +61,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
-#include <sys/sysctl.h>
#include <sys/bus.h>
-#include <sys/timetc.h>
#include <sys/interrupt.h>
+#include <sys/pcpu.h>
+#include <sys/sysctl.h>
+#include <sys/timetc.h>
#include <dev/ofw/openfirm.h>
@@ -76,11 +77,9 @@ __FBSDID("$FreeBSD$");
/*
* Initially we assume a processor with a bus frequency of 12.5 MHz.
*/
-u_int tickspending;
u_long ns_per_tick = 80;
static u_long ticks_per_sec = 12500000;
static long ticks_per_intr;
-static volatile u_long lasttb;
static timecounter_get_t decr_get_timecount;
@@ -95,7 +94,6 @@ static struct timecounter decr_timecounter = {
void
decr_intr(struct trapframe *frame)
{
- u_long tb;
long tick;
int nticks;
@@ -109,36 +107,17 @@ decr_intr(struct trapframe *frame)
* Based on the actual time delay since the last decrementer reload,
* we arrange for earlier interrupt next time.
*/
- __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick));
+ __asm ("mfdec %0" : "=r"(tick));
for (nticks = 0; tick < 0; nticks++)
tick += ticks_per_intr;
mtdec(tick);
- /*
- * lasttb is used during microtime. Set it to the virtual
- * start of this tick interval.
- */
- lasttb = tb + tick - ticks_per_intr;
- nticks += tickspending;
- tickspending = 0;
-
- /*
- * Reenable interrupts
- */
-#if 0
- msr = mfmsr();
- mtmsr(msr | PSL_EE | PSL_RI);
-#endif
- /*
- * Do standard timer interrupt stuff.
- * Do softclock stuff only on the last iteration.
- */
-#if 0
- while (--nticks > 0) {
- hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+ while (nticks-- > 0) {
+ if (PCPU_GET(cpuid) == 0)
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+ else
+ hardclock_cpu(TRAPF_USERMODE(frame));
}
-#endif
- hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
}
void
@@ -166,7 +145,6 @@ decr_init(void)
ns_per_tick = 1000000000 / ticks_per_sec;
ticks_per_intr = ticks_per_sec / hz;
- __asm __volatile ("mftb %0" : "=r"(lasttb));
mtdec(ticks_per_intr);
mtmsr(msr);
diff --git a/sys/powerpc/aim/locore.S b/sys/powerpc/aim/locore.S
index 235e13a03273..ed5c7b87a560 100644
--- a/sys/powerpc/aim/locore.S
+++ b/sys/powerpc/aim/locore.S
@@ -77,20 +77,21 @@
.globl kernbase
.set kernbase, KERNBASE
+#define TMPSTKSZ 8192 /* 8K temporary stack */
+
/*
* Globals
*/
.data
.align 4
GLOBAL(tmpstk)
- .space 8192
+ .space TMPSTKSZ
GLOBAL(esym)
.long 0 /* end of symbol table */
GLOBAL(ofmsr)
.long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
-#define INTSTK 16384 /* 16K interrupt stack */
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
@@ -152,9 +153,8 @@ __start:
stw 5,openfirmware_entry@l(8) /* save client interface handler */
mr 3,5
- lis 1,tmpstk@ha
- addi 1,1,tmpstk@l
- addi 1,1,8192-16
+ lis 1,(tmpstk+TMPSTKSZ-16)@ha
+ addi 1,1,(tmpstk+TMPSTKSZ-16)@l
mfmsr 0
lis 9,ofmsr@ha
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 15decb7999e4..6a6f407edad4 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -129,7 +129,8 @@ extern vm_offset_t ksym_start, ksym_end;
int cold = 1;
-static struct pcpu pcpu0;
+struct pcpu __pcpu[MAXCPU];
+
static struct trapframe frame0;
char machine[] = "powerpc";
@@ -236,6 +237,9 @@ cpu_startup(void *dummy)
extern char kernel_text[], _end[];
+#ifdef SMP
+extern void *rstcode, *rstsize;
+#endif
extern void *trapcode, *trapsize;
extern void *alitrap, *alisize;
extern void *dsitrap, *dsisize;
@@ -288,7 +292,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
/*
* Set up per-cpu data.
*/
- pc = &pcpu0;
+ pc = __pcpu;
pcpu_init(pc, 0, sizeof(struct pcpu));
pc->pc_curthread = &thread0;
pc->pc_cpuid = 0;
@@ -320,7 +324,11 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
*/
mtmsr(mfmsr() & ~(PSL_IR | PSL_DR));
isync();
+#ifdef SMP
+ bcopy(&rstcode, (void *)EXC_RST, (size_t)&rstsize);
+#else
bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize);
+#endif
bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize);
bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize);
@@ -337,8 +345,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize);
bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize);
#ifdef KDB
- bcopy(&dblow, (void *)EXC_RST, (size_t)&dbsize);
- bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize);
+ bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize);
bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize);
bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize);
bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize);
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index d76fc2378828..d179b4081c21 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -147,6 +147,7 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
#include <machine/psl.h>
#include <machine/pte.h>
+#include <machine/smp.h>
#include <machine/sr.h>
#include <machine/mmuvar.h>
@@ -203,8 +204,6 @@ static struct ofw_map *translations;
extern struct pmap ofw_pmap;
-
-
/*
* Lock for the pteg and pvo tables.
*/
@@ -605,6 +604,59 @@ om_cmp(const void *a, const void *b)
}
void
+pmap_cpu_bootstrap(volatile uint32_t *trcp, int ap)
+{
+ u_int sdr;
+ int i;
+
+ trcp[0] = 0x1000;
+ trcp[1] = (uint32_t)&pmap_cpu_bootstrap;
+
+ if (ap) {
+ __asm __volatile("mtdbatu 0,%0" :: "r"(battable[0].batu));
+ __asm __volatile("mtdbatl 0,%0" :: "r"(battable[0].batl));
+ isync();
+ __asm __volatile("mtibatu 0,%0" :: "r"(battable[0].batu));
+ __asm __volatile("mtibatl 0,%0" :: "r"(battable[0].batl));
+ isync();
+ }
+
+ trcp[0] = 0x1001;
+
+ for (i = 1; i < 4; i++) {
+ __asm __volatile("mtdbatu %0,%1" :: "n"(i), "r"(0));
+ __asm __volatile("mtibatu %0,%1" :: "n"(i), "r"(0));
+ isync();
+ }
+
+ trcp[0] = 0x1002;
+
+ __asm __volatile("mtdbatu 1,%0" :: "r"(battable[8].batu));
+ __asm __volatile("mtdbatl 1,%0" :: "r"(battable[8].batl));
+ isync();
+
+ trcp[0] = 0x1003;
+
+ for (i = 0; i < 16; i++)
+ mtsrin(i << ADDR_SR_SHFT, EMPTY_SEGMENT);
+
+ trcp[0] = 0x1004;
+
+ __asm __volatile("mtsr %0,%1" :: "n"(KERNEL_SR), "r"(KERNEL_SEGMENT));
+ __asm __volatile("mtsr %0,%1" :: "n"(KERNEL2_SR), "r"(KERNEL2_SEGMENT));
+ __asm __volatile("sync");
+
+ trcp[0] = 0x1005;
+
+ sdr = (u_int)moea_pteg_table | (moea_pteg_mask >> 10);
+ __asm __volatile("mtsdr1 %0" :: "r"(sdr));
+ isync();
+
+ trcp[0] = 0x1006;
+ trcp[1] = sdr;
+}
+
+void
moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
{
ihandle_t mmui;
@@ -612,9 +664,9 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
int sz;
int i, j;
int ofw_mappings;
+ uint32_t trace[2];
vm_size_t size, physsz, hwphyssz;
vm_offset_t pa, va, off;
- u_int batl, batu;
/*
* Set up BAT0 to map the lowest 256 MB area
@@ -647,18 +699,15 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
* Use an IBAT and a DBAT to map the bottom segment of memory
* where we are.
*/
- batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
- batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
__asm (".balign 32; \n"
"mtibatu 0,%0; mtibatl 0,%1; isync; \n"
"mtdbatu 0,%0; mtdbatl 0,%1; isync"
- :: "r"(batu), "r"(batl));
+ :: "r"(battable[0].batu), "r"(battable[0].batl));
/* map pci space */
- batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
- batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW);
- __asm ("mtdbatu 1,%0; mtdbatl 1,%1; isync"
- :: "r"(batu), "r"(batl));
+ __asm __volatile("mtdbatu 1,%0" :: "r"(battable[8].batu));
+ __asm __volatile("mtdbatl 1,%0" :: "r"(battable[8].batl));
+ isync();
mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
CTR0(KTR_PMAP, "moea_bootstrap: physical memory");
@@ -844,18 +893,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
kernel_pmap->pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT;
kernel_pmap->pm_active = ~0;
- /*
- * Initialize hardware.
- */
- for (i = 0; i < 16; i++) {
- mtsrin(i << ADDR_SR_SHFT, EMPTY_SEGMENT);
- }
- __asm __volatile ("mtsr %0,%1"
- :: "n"(KERNEL_SR), "r"(KERNEL_SEGMENT));
- __asm __volatile ("mtsr %0,%1"
- :: "n"(KERNEL2_SR), "r"(KERNEL2_SEGMENT));
- __asm __volatile ("sync; mtsdr1 %0; isync"
- :: "r"((u_int)moea_pteg_table | (moea_pteg_mask >> 10)));
+ pmap_cpu_bootstrap(trace, 0);
tlbia();
pmap_bootstrapped++;
diff --git a/sys/powerpc/aim/mp_cpudep.c b/sys/powerpc/aim/mp_cpudep.c
new file mode 100644
index 000000000000..5b867dd6ab3b
--- /dev/null
+++ b/sys/powerpc/aim/mp_cpudep.c
@@ -0,0 +1,231 @@
+/*-
+ * Copyright (c) 2008 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <machine/bat.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/intr_machdep.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/trap_aim.h>
+
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+
+extern void *rstcode;
+
+void *ap_pcpu;
+
+static int
+powerpc_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu)
+{
+ int cpuid, res;
+
+ cpuref->cr_hwref = cpu;
+ res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+ if (res < 0)
+ return (ENOENT);
+
+ cpuref->cr_cpuid = cpuid & 0xff;
+ return (0);
+}
+
+int
+powerpc_smp_first_cpu(struct cpuref *cpuref)
+{
+ char buf[8];
+ phandle_t cpu, dev, root;
+ int res;
+
+ root = OF_peer(0);
+
+ dev = OF_child(root);
+ while (dev != 0) {
+ res = OF_getprop(dev, "name", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpus") == 0)
+ break;
+ dev = OF_peer(dev);
+ }
+ if (dev == 0)
+ return (ENOENT);
+
+ cpu = OF_child(dev);
+ while (cpu != 0) {
+ res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpu") == 0)
+ break;
+ cpu = OF_peer(cpu);
+ }
+ if (cpu == 0)
+ return (ENOENT);
+
+ return (powerpc_smp_fill_cpuref(cpuref, cpu));
+}
+
+int
+powerpc_smp_next_cpu(struct cpuref *cpuref)
+{
+ char buf[8];
+ phandle_t cpu;
+ int res;
+
+ cpu = OF_peer(cpuref->cr_hwref);
+ while (cpu != 0) {
+ res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpu") == 0)
+ break;
+ cpu = OF_peer(cpu);
+ }
+ if (cpu == 0)
+ return (ENOENT);
+
+ return (powerpc_smp_fill_cpuref(cpuref, cpu));
+}
+
+int
+powerpc_smp_get_bsp(struct cpuref *cpuref)
+{
+ ihandle_t inst;
+ phandle_t bsp, chosen;
+ int res;
+
+ chosen = OF_finddevice("/chosen");
+ if (chosen == 0)
+ return (ENXIO);
+
+ res = OF_getprop(chosen, "cpu", &inst, sizeof(inst));
+ if (res < 0)
+ return (ENXIO);
+
+ bsp = OF_instance_to_package(inst);
+ return (powerpc_smp_fill_cpuref(cpuref, bsp));
+}
+
+uint32_t
+cpudep_ap_bootstrap(volatile uint32_t *trcp)
+{
+ uint32_t hid, msr, sp;
+
+ trcp[0] = 0x2000;
+ trcp[1] = (uint32_t)&cpudep_ap_bootstrap;
+
+ __asm __volatile("mtsprg 0, %0" :: "r"(ap_pcpu));
+ __asm __volatile("sync");
+
+ trcp[0] = 0x2001;
+ trcp[1] = (uint32_t)pcpup;
+
+ hid = mfspr(SPR_HID0);
+ hid &= ~(HID0_ICE | HID0_DCE);
+ hid &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP);
+ mtspr(SPR_HID0, hid);
+ isync();
+
+ trcp[0] = 0x2002;
+ trcp[1] = hid;
+
+ hid |= HID0_ICFI | HID0_DCFI;
+ hid |= HID0_ICE | HID0_DCE;
+ mtspr(SPR_HID0, hid);
+ isync();
+
+ trcp[0] = 0x2003;
+ trcp[1] = hid;
+
+ msr = PSL_IR | PSL_DR | PSL_ME;
+ mtmsr(msr);
+ isync();
+
+ trcp[0] = 0x2004;
+ trcp[1] = msr;
+
+ hid |= HID0_NAP | HID0_DPM;
+ mtspr(SPR_HID0, hid);
+ isync();
+
+ trcp[0] = 0x2005;
+ trcp[1] = hid;
+
+ pcpup->pc_curthread = pcpup->pc_idlethread;
+ pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb;
+ sp = pcpup->pc_curpcb->pcb_sp;
+
+ trcp[0] = 0x2006;
+ trcp[1] = sp;
+
+ return (sp);
+}
+
+int
+powerpc_smp_start_cpu(struct pcpu *pc)
+{
+ phandle_t cpu;
+ volatile uint32_t *trcp;
+ volatile uint8_t *rstvec;
+ uint32_t trace;
+ int res, reset, timeout;
+
+ cpu = pc->pc_hwref;
+ res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset));
+ if (res < 0)
+ return (ENXIO);
+
+ trcp = (uint32_t *)(EXC_RST + 4);
+ trace = *trcp;
+
+ ap_pcpu = pc;
+
+ rstvec = (uint8_t *)(0x80000000 + reset);
+
+ *rstvec = 4;
+ __asm __volatile("sync");
+ DELAY(1);
+ *rstvec = 0;
+ __asm __volatile("sync");
+
+ timeout = 1000;
+ while (!pc->pc_awake && timeout--)
+ DELAY(100);
+
+ if (!pc->pc_awake)
+ printf("XXX: timeout (trace=%x; data=%x)\n", trcp[0], trcp[1]);
+
+ return (0);
+}
diff --git a/sys/powerpc/aim/swtch.S b/sys/powerpc/aim/swtch.S
index 70b5b4f082d2..0d6875d836ab 100644
--- a/sys/powerpc/aim/swtch.S
+++ b/sys/powerpc/aim/swtch.S
@@ -67,6 +67,13 @@
#include <machine/asm.h>
/*
+ * void cpu_throw(struct thread *old, struct thread *new)
+ */
+ENTRY(cpu_throw)
+ mr %r15, %r4
+ b cpu_switchin
+
+/*
* void cpu_switch(struct thread *old,
* struct thread *new,
* struct mutex *mtx);
@@ -94,7 +101,8 @@ ENTRY(cpu_switch)
mr %r14,%r3 /* Copy the old thread ptr... */
mr %r15,%r4 /* and the new thread ptr in scratch */
- lwz %r6,PCB_FLAGS(%r5) /* Save FPU context if needed */
+ lwz %r6,PCB_FLAGS(%r5)
+ /* Save FPU context if needed */
andi. %r6, %r6, PCB_FPU
beq .L1
bl save_fpu
@@ -102,6 +110,7 @@ ENTRY(cpu_switch)
.L1:
bl pmap_deactivate /* Deactivate the current pmap */
+cpu_switchin:
mr %r3,%r15 /* Get new thread ptr */
bl pmap_activate /* Activate the new address space */
@@ -110,7 +119,8 @@ ENTRY(cpu_switch)
lwz %r17,TD_PCB(%r15) /* Store new current PCB */
stw %r17,PC_CURPCB(%r7)
- lwz %r6, PCB_FLAGS(%r17) /* Restore FPU context if needed */
+ lwz %r6, PCB_FLAGS(%r17)
+ /* Restore FPU context if needed */
andi. %r6, %r6, PCB_FPU
beq .L2
mr %r3,%r15 /* Pass curthread to enable_fpu */
diff --git a/sys/powerpc/aim/trap_subr.S b/sys/powerpc/aim/trap_subr.S
index 03fb7ec79830..2c0e78f86cb3 100644
--- a/sys/powerpc/aim/trap_subr.S
+++ b/sys/powerpc/aim/trap_subr.S
@@ -228,20 +228,67 @@
mfsprg2 %r2; /* restore r2 & r3 */ \
mfsprg3 %r3
-#ifdef KDB
+#ifdef SMP
/*
- * Define the kdb debugger stack
+ * Processor reset exception handler. These are typically
+ * the first instructions the processor executes after a
+ * software reset.
*/
- .data
-GLOBAL(dbstk)
- .space INTSTK+8 /* kdb stack */
+ .globl CNAME(rstcode), CNAME(rstsize)
+CNAME(rstcode):
+ bl 1f
+
+ /* We use this space for tracing purposes. */
+ .long 0
+ .long 0
+
+1:
+ mflr %r2
+ mfmsr %r3
+ stw %r2,0(%r2) /* trace: 0x104 - we're here. */
+ stw %r3,4(%r2) /* trace data: MSR */
+ sync
+
+ lis %r1,(tmpstk+TMPSTKSZ-16)@ha
+ addi %r1,%r1,(tmpstk+TMPSTKSZ-16)@l
+
+ addi %r3,%r2,4
+ stw %r3,0(%r1)
+ sync
+ stw %r3,0(%r2) /* trace: 0x108 - stack is writable */
+ stw %r1,4(%r2) /* trace data: SP */
+ sync
+
+ mr %r3,%r2
+ lis %r4,1@l
+ bla CNAME(pmap_cpu_bootstrap)
+
+ addi %r3,%r2,8
+ stw %r3,0(%r2) /* trace 0x10c - back from 1st call */
+ sync
+
+ mr %r3,%r2
+ bla CNAME(cpudep_ap_bootstrap)
+ mr %r1,%r3
+
+ addi %r3,%r2,12
+ stw %r3,0(%r2) /* trace 0x110 - back from 2nd call */
+ stw %r1,4(%r2) /* trace data: SP */
+
+ mr %r3,%r2
+ bla CNAME(machdep_ap_bootstrap)
+
+ /* Should not be reached */
+9:
+ b 9b
+CNAME(rstsize) = . - CNAME(rstcode)
#endif
/*
* This code gets copied to all the trap vectors
* (except ISI/DSI, ALI, and the interrupts)
*/
- .text
+
.globl CNAME(trapcode),CNAME(trapsize)
CNAME(trapcode):
mtsprg1 %r1 /* save SP */
@@ -385,8 +432,8 @@ disitrap:
stw %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */
lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */
stw %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */
- lis %r1,dbstk+INTSTK@ha /* get new SP */
- addi %r1,%r1,dbstk+INTSTK@l
+ lis %r1,(tmpstk+TMPSTKSZ-16)@ha /* get new SP */
+ addi %r1,%r1,(tmpstk+TMPSTKSZ-16)@l
b dbtrap
#endif
@@ -457,8 +504,8 @@ CNAME(vectrapsize) = .-CNAME(vectrap)
/*
* Deliberate entry to dbtrap
*/
- .globl CNAME(ppc_db_trap)
-CNAME(ppc_db_trap):
+ .globl CNAME(breakpoint)
+CNAME(breakpoint):
mtsprg1 %r1
mfmsr %r3
mtsrr1 %r3
@@ -533,8 +580,8 @@ CNAME(dblow):
stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */
stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */
mflr %r28 /* save LR */
- lis %r1,dbstk+INTSTK@ha /* get new SP */
- addi %r1,%r1,dbstk+INTSTK@l
+ lis %r1,(tmpstk+TMPSTKSZ-16)@ha /* get new SP */
+ addi %r1,%r1,(tmpstk+TMPSTKSZ-16)@l
bla dbtrap
CNAME(dbsize) = .-CNAME(dblow)
#endif /* KDB */
diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c
index 5bd1e2b6815c..33b3382bd449 100644
--- a/sys/powerpc/aim/vm_machdep.c
+++ b/sys/powerpc/aim/vm_machdep.c
@@ -192,15 +192,6 @@ cpu_exit(td)
{
}
-/* Temporary helper */
-void
-cpu_throw(struct thread *old, struct thread *new)
-{
-
- cpu_switch(old, new, old->td_lock);
- panic("cpu_throw() didn't");
-}
-
/*
* Reset back to firmware.
*/
diff --git a/sys/powerpc/booke/trap_subr.S b/sys/powerpc/booke/trap_subr.S
index f9da569a03fd..f22a0ceefda8 100644
--- a/sys/powerpc/booke/trap_subr.S
+++ b/sys/powerpc/booke/trap_subr.S
@@ -795,8 +795,8 @@ CNAME(asttrapexit):
/*
* Deliberate entry to dbtrap
*/
- .globl CNAME(ppc_db_trap)
-CNAME(ppc_db_trap):
+ .globl CNAME(breakpoint)
+CNAME(breakpoint):
mtsprg1 %r1
mfmsr %r3
mtsrr1 %r3
diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES
index a399e9cc6b58..090f388f09d6 100644
--- a/sys/powerpc/conf/NOTES
+++ b/sys/powerpc/conf/NOTES
@@ -61,8 +61,6 @@ nodevice dcons_crom
#####################################################################
# Options we don't want to deal with
-nooption SMP
-nooption ADAPTIVE_SX
nooption PPC_DEBUG
nooption PPC_PROBE_CHIPSET
nooption SC_NO_MODE_CHANGE
diff --git a/sys/powerpc/include/cpufunc.h b/sys/powerpc/include/cpufunc.h
index a58d4c531673..6928fc3eb481 100644
--- a/sys/powerpc/include/cpufunc.h
+++ b/sys/powerpc/include/cpufunc.h
@@ -49,17 +49,9 @@ powerpc_mb(void)
struct thread;
#ifdef KDB
-void ppc_db_trap(void);
+void breakpoint(void);
#endif
-static __inline void
-breakpoint(void)
-{
-#ifdef KDB
- ppc_db_trap();
-#endif
-}
-
/* CPU register mangling inlines */
static __inline void
diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h
index 3970ad542744..af9e54b2e0d5 100644
--- a/sys/powerpc/include/pcpu.h
+++ b/sys/powerpc/include/pcpu.h
@@ -40,6 +40,11 @@ struct pmap;
int pc_inside_intr; \
struct pmap *pc_curpmap; /* current pmap */ \
struct thread *pc_fputhread; /* current fpu user */ \
+ uintptr_t pc_hwref; \
+ uint32_t pc_pir; \
+ int pc_bsp:1; \
+ int pc_awake:1; \
+ uint32_t pc_ipimask; \
register_t pc_tempsave[CPUSAVE_LEN]; \
register_t pc_disisave[CPUSAVE_LEN]; \
register_t pc_dbsave[CPUSAVE_LEN];
@@ -112,18 +117,18 @@ struct pmap;
int pc_md_placeholder
#endif
-#define PCPUP ((struct pcpu *) powerpc_get_pcpup())
+#define pcpup ((struct pcpu *) powerpc_get_pcpup())
-#define PCPU_GET(member) (PCPUP->pc_ ## member)
+#define PCPU_GET(member) (pcpup->pc_ ## member)
/*
* XXX The implementation of this operation should be made atomic
* with respect to preemption.
*/
-#define PCPU_ADD(member, value) (PCPUP->pc_ ## member += (value))
+#define PCPU_ADD(member, value) (pcpup->pc_ ## member += (value))
#define PCPU_INC(member) PCPU_ADD(member, 1)
-#define PCPU_PTR(member) (&PCPUP->pc_ ## member)
-#define PCPU_SET(member,value) (PCPUP->pc_ ## member = (value))
+#define PCPU_PTR(member) (&pcpup->pc_ ## member)
+#define PCPU_SET(member,value) (pcpup->pc_ ## member = (value))
#endif /* _KERNEL */
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
index d9d75914af16..dbf3cfc19e6f 100644
--- a/sys/powerpc/powerpc/intr_machdep.c
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -78,6 +78,7 @@
#include <machine/frame.h>
#include <machine/intr_machdep.h>
#include <machine/md_var.h>
+#include <machine/smp.h>
#include <machine/trap.h>
#include "pic_if.h"
@@ -99,6 +100,12 @@ static struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
static u_int nvectors; /* Allocated vectors */
static u_int stray_count;
+#ifdef SMP
+static void *ipi_cookie;
+#endif
+
+static u_int ipi_irq;
+
device_t pic;
static void
@@ -190,14 +197,31 @@ powerpc_register_pic(device_t dev, u_int ipi)
{
pic = dev;
+ ipi_irq = ipi;
}
int
powerpc_enable_intr(void)
{
struct powerpc_intr *i;
+#ifdef SMP
+ int error;
+#endif
int vector;
+ if (pic == NULL)
+ panic("no PIC detected\n");
+
+#ifdef SMP
+ /* Install an IPI handler. */
+ error = powerpc_setup_intr("IPI", ipi_irq, powerpc_ipi_handler,
+ NULL, NULL, INTR_TYPE_MISC | INTR_EXCL | INTR_FAST, &ipi_cookie);
+ if (error) {
+ printf("unable to setup IPI handler\n");
+ return (error);
+ }
+#endif
+
for (vector = 0; vector < nvectors; vector++) {
i = powerpc_intrs[vector];
if (i == NULL)
@@ -211,6 +235,11 @@ powerpc_enable_intr(void)
PIC_ENABLE(pic, i->irq, vector);
}
+#ifdef SMP
+ /* Send ourself a test IPI message. */
+ ipi_self(IPI_PPC_TEST);
+#endif
+
return (0);
}
diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c
index 0c9dbe0d7a89..c21f9db511be 100644
--- a/sys/powerpc/powerpc/mp_machdep.c
+++ b/sys/powerpc/powerpc/mp_machdep.c
@@ -1,75 +1,316 @@
/*-
- * Copyright (c) 2000 Doug Rabson
+ * Copyright (c) 2008 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
+ *
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/ktr.h>
-#include <sys/proc.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
#include <sys/smp.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr_machdep.h>
+#include <machine/smp.h>
+
+#include "pic_if.h"
+
+extern struct pcpu __pcpu[MAXCPU];
+
+volatile static int ap_awake;
+volatile static u_int ap_state;
+volatile static uint32_t ap_decr;
+
+int mp_ipi_test = 0;
+
+void
+machdep_ap_bootstrap(volatile uint32_t *trcp)
+{
+
+ trcp[0] = 0x3000;
+ trcp[1] = (uint32_t)&machdep_ap_bootstrap;
+
+ // __asm __volatile("mtspr 1023,%0" :: "r"(PCPU_GET(cpuid)));
+ __asm __volatile("mfspr %0,1023" : "=r"(pcpup->pc_pir));
+ pcpup->pc_awake = 1;
+
+ while (ap_state == 0)
+ ;
+
+ __asm __volatile("mtdec %0" :: "r"(ap_decr));
+
+ ap_awake++;
-#include <machine/atomic.h>
-#include <machine/pmap.h>
+ /* Initialize curthread. */
+ PCPU_SET(curthread, PCPU_GET(idlethread));
-int boot_cpu_id;
+ mtmsr(mfmsr() | PSL_EE | PSL_RI);
+ sched_throw(NULL);
+}
struct cpu_group *
cpu_topo(void)
{
- return smp_topo_none();
+ return (smp_topo_none());
}
void
cpu_mp_setmaxid(void)
{
+ struct cpuref cpuref;
+ int error;
+
+ mp_ncpus = 0;
+ error = powerpc_smp_first_cpu(&cpuref);
+ while (!error) {
+ mp_ncpus++;
+ error = powerpc_smp_next_cpu(&cpuref);
+ }
+ /* Sanity. */
+ if (mp_ncpus == 0)
+ mp_ncpus = 1;
+
+ /*
+ * Set the largest cpuid we're going to use. This is necessary
+ * for VM initialization.
+ */
+ mp_maxid = min(mp_ncpus, MAXCPU) - 1;
}
int
cpu_mp_probe(void)
{
- all_cpus = 1; /* needed for MB init code */
- return 0;
+
+ /*
+ * We're not going to enable SMP if there's only 1 processor.
+ */
+ return (mp_ncpus > 1);
}
void
cpu_mp_start(void)
{
+ struct cpuref bsp, cpu;
+ struct pcpu *pc;
+ int error;
+
+ error = powerpc_smp_get_bsp(&bsp);
+ KASSERT(error == 0, ("Don't know BSP"));
+ KASSERT(bsp.cr_cpuid == 0, ("%s: cpuid != 0", __func__));
+
+ error = powerpc_smp_first_cpu(&cpu);
+ while (!error) {
+ if (cpu.cr_cpuid >= MAXCPU) {
+ printf("SMP: cpu%d: skipped -- ID out of range\n",
+ cpu.cr_cpuid);
+ goto next;
+ }
+ if (all_cpus & (1 << cpu.cr_cpuid)) {
+ printf("SMP: cpu%d: skipped - duplicate ID\n",
+ cpu.cr_cpuid);
+ goto next;
+ }
+ if (cpu.cr_cpuid != bsp.cr_cpuid) {
+ pc = &__pcpu[cpu.cr_cpuid];
+ pcpu_init(pc, cpu.cr_cpuid, sizeof(*pc));
+ } else {
+ pc = pcpup;
+ pc->pc_cpuid = bsp.cr_cpuid;
+ pc->pc_bsp = 1;
+ }
+ pc->pc_cpumask = 1 << pc->pc_cpuid;
+ pc->pc_hwref = cpu.cr_hwref;
+ all_cpus |= pc->pc_cpumask;
+
+ next:
+ error = powerpc_smp_next_cpu(&cpu);
+ }
}
void
cpu_mp_announce(void)
{
+ struct pcpu *pc;
+ int i;
+
+ for (i = 0; i <= mp_maxid; i++) {
+ pc = pcpu_find(i);
+ if (pc == NULL)
+ continue;
+ printf("cpu%d: dev=%x", i, pc->pc_hwref);
+ if (pc->pc_bsp)
+ printf(" (BSP)");
+ printf("\n");
+ }
+}
+
+static void
+cpu_mp_unleash(void *dummy)
+{
+ struct pcpu *pc;
+ int cpus;
+
+ if (mp_ncpus <= 1)
+ return;
+
+ if (mp_ipi_test != 1) {
+ printf("SMP: ERROR: sending of a test IPI failed\n");
+ return;
+ }
+
+ cpus = 0;
+ smp_cpus = 0;
+ SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ cpus++;
+ pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask;
+ if (!pc->pc_bsp) {
+ printf("Waking up CPU %d (dev=%x)\n", pc->pc_cpuid,
+ pc->pc_hwref);
+ powerpc_smp_start_cpu(pc);
+ } else {
+ __asm __volatile("mfspr %0,1023" : "=r"(pc->pc_pir));
+ pc->pc_awake = 1;
+ }
+ if (pc->pc_awake)
+ smp_cpus++;
+ }
+
+ ap_awake = 1;
+ __asm __volatile("mfdec %0" : "=r"(ap_decr));
+ ap_state++;
+
+ while (ap_awake < smp_cpus)
+ ;
+
+ if (smp_cpus != cpus || cpus != mp_ncpus) {
+ printf("SMP: %d CPUs found; %d CPUs usable; %d CPUs woken\n",
+ mp_ncpus, cpus, smp_cpus);
+ }
+
+ smp_active = 1;
+ smp_started = 1;
+}
+
+SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
+
+static u_int ipi_msg_cnt[32];
+
+int
+powerpc_ipi_handler(void *arg)
+{
+ cpumask_t self;
+ uint32_t ipimask;
+ int msg;
+
+ ipimask = atomic_readandclear_32(&(pcpup->pc_ipimask));
+ if (ipimask == 0)
+ return (FILTER_STRAY);
+ while ((msg = ffs(ipimask) - 1) != -1) {
+ ipimask &= ~(1u << msg);
+ ipi_msg_cnt[msg]++;
+ switch (msg) {
+ case IPI_AST:
+ break;
+ case IPI_PREEMPT:
+ sched_preempt(curthread);
+ break;
+ case IPI_RENDEZVOUS:
+ smp_rendezvous_action();
+ break;
+ case IPI_STOP:
+ self = PCPU_GET(cpumask);
+ savectx(PCPU_GET(curpcb));
+ atomic_set_int(&stopped_cpus, self);
+ while ((started_cpus & self) == 0)
+ cpu_spinwait();
+ atomic_clear_int(&started_cpus, self);
+ atomic_clear_int(&stopped_cpus, self);
+ break;
+ case IPI_PPC_TEST:
+ mp_ipi_test++;
+ break;
+ }
+ }
+
+ return (FILTER_HANDLED);
+}
+
+static void
+ipi_send(struct pcpu *pc, int ipi)
+{
+
+ atomic_set_32(&pc->pc_ipimask, (1 << ipi));
+ PIC_IPI(pic, pc->pc_cpuid);
+}
+
+/* Send an IPI to a set of cpus. */
+void
+ipi_selected(cpumask_t cpus, int ipi)
+{
+ struct pcpu *pc;
+
+ SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ if (cpus & pc->pc_cpumask)
+ ipi_send(pc, ipi);
+ }
+}
+
+/* Send an IPI to all CPUs, including myself. */
+void
+ipi_all(int ipi)
+{
+ struct pcpu *pc;
+
+ SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ ipi_send(pc, ipi);
+ }
+}
+
+/* Send an IPI to all CPUs EXCEPT myself. */
+void
+ipi_all_but_self(int ipi)
+{
+ struct pcpu *pc;
+
+ SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ if (pc != pcpup)
+ ipi_send(pc, ipi);
+ }
+}
+
+/* Send an IPI to myself. */
+void
+ipi_self(int ipi)
+{
+
+ ipi_send(pcpup, ipi);
}
diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c
index c778a2495d8f..88d2614cb288 100644
--- a/sys/powerpc/powerpc/openpic.c
+++ b/sys/powerpc/powerpc/openpic.c
@@ -82,7 +82,7 @@ int
openpic_attach(device_t dev)
{
struct openpic_softc *sc;
- u_int ipi, irq;
+ u_int cpu, ipi, irq;
u_int32_t x;
sc = device_get_softc(dev);
@@ -132,6 +132,9 @@ openpic_attach(device_t dev)
"Version %s, supports %d CPUs and %d irqs\n",
sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
+ for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
+ openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15);
+
/* Reset and disable all interrupts. */
for (irq = 0; irq < sc->sc_nirq; irq++) {
x = irq; /* irq == vector. */
@@ -150,8 +153,6 @@ openpic_attach(device_t dev)
openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
}
- openpic_set_priority(sc, 15);
-
/* we don't need 8259 passthrough mode */
x = openpic_read(sc, OPENPIC_CONFIG);
x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
@@ -161,9 +162,8 @@ openpic_attach(device_t dev)
for (irq = 0; irq < sc->sc_nirq; irq++)
openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
- /* XXX set spurious intr vector */
-
- openpic_set_priority(sc, 0);
+ for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
+ openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);
/* clear all pending interrupts */
for (irq = 0; irq < sc->sc_nirq; irq++) {
@@ -203,15 +203,25 @@ openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
void
openpic_dispatch(device_t dev, struct trapframe *tf)
{
+ static int once = 0;
struct openpic_softc *sc;
u_int vector;
+ if (once == 0 && PCPU_GET(cpuid) != 0) {
+ printf("XXX: got interrupt!\n");
+ once++;
+ }
+
sc = device_get_softc(dev);
while (1) {
vector = openpic_read(sc, OPENPIC_PCPU_IACK(PCPU_GET(cpuid)));
vector &= OPENPIC_VECTOR_MASK;
if (vector == 255)
break;
+ if (once == 1 && PCPU_GET(cpuid) != 0) {
+ printf("XXX: got vector %u\n", vector);
+ once++;
+ }
powerpc_dispatch_intr(vector, tf);
}
}