diff options
Diffstat (limited to 'sys/alpha')
-rw-r--r-- | sys/alpha/alpha/db_interface.c | 65 | ||||
-rw-r--r-- | sys/alpha/alpha/interrupt.c | 31 | ||||
-rw-r--r-- | sys/alpha/alpha/machdep.c | 18 | ||||
-rw-r--r-- | sys/alpha/alpha/mp_machdep.c | 683 | ||||
-rw-r--r-- | sys/alpha/alpha/pmap.c | 2 | ||||
-rw-r--r-- | sys/alpha/alpha/trap.c | 6 | ||||
-rw-r--r-- | sys/alpha/include/cpu.h | 1 | ||||
-rw-r--r-- | sys/alpha/include/globaldata.h | 7 | ||||
-rw-r--r-- | sys/alpha/include/ipl.h | 19 | ||||
-rw-r--r-- | sys/alpha/include/pcpu.h | 7 | ||||
-rw-r--r-- | sys/alpha/include/smp.h | 45 |
11 files changed, 115 insertions, 769 deletions
diff --git a/sys/alpha/alpha/db_interface.c b/sys/alpha/alpha/db_interface.c index d6b1297..e94a490 100644 --- a/sys/alpha/alpha/db_interface.c +++ b/sys/alpha/alpha/db_interface.c @@ -60,13 +60,13 @@ #include <sys/cons.h> #include <sys/ktr.h> #include <sys/mutex.h> +#include <sys/smp.h> #include <vm/vm.h> #include <machine/db_machdep.h> #include <machine/pal.h> #include <machine/prom.h> -#include <machine/smp.h> #include <alpha/alpha/db_instruction.h> @@ -573,45 +573,46 @@ db_branch_taken(ins, pc, regs) DB_SHOW_COMMAND(pcpu, db_show_pcpu) { struct globaldata *gd; +#ifdef SMP int id; if (have_addr) id = ((addr >> 4) % 16) * 10 + (addr % 16); else id = PCPU_GET(cpuid); - SLIST_FOREACH(gd, &cpuhead, gd_allcpu) { - if (gd->gd_cpuid == id) - break; - } - if (gd == NULL) + gd = globaldata_find(id); + if (gd == NULL) { db_printf("CPU %d not found\n", id); - else { - db_printf("cpuid = %d\n", gd->gd_cpuid); - db_printf("ipis = %lx\n", gd->gd_pending_ipis); - db_printf("next ASN = %d\n", gd->gd_next_asn); - db_printf("curproc = "); - if (gd->gd_curproc != NULL) - db_printf("%p: pid %d \"%s\"\n", gd->gd_curproc, - gd->gd_curproc->p_pid, gd->gd_curproc->p_comm); - else - db_printf("none\n"); - db_printf("curpcb = %p\n", gd->gd_curpcb); - db_printf("fpcurproc = "); - if (gd->gd_fpcurproc != NULL) - db_printf("%p: pid %d \"%s\"\n", gd->gd_fpcurproc, - gd->gd_fpcurproc->p_pid, gd->gd_fpcurproc->p_comm); - else - db_printf("none\n"); - db_printf("idleproc = "); - if (gd->gd_idleproc != NULL) - db_printf("%p: pid %d \"%s\"\n", gd->gd_idleproc, - gd->gd_idleproc->p_pid, gd->gd_idleproc->p_comm); - else - db_printf("none\n"); + return; + } +#else + gd = GLOBALP; +#endif + db_printf("cpuid = %d\n", gd->gd_cpuid); + db_printf("ipis = %lx\n", gd->gd_pending_ipis); + db_printf("next ASN = %d\n", gd->gd_next_asn); + db_printf("curproc = "); + if (gd->gd_curproc != NULL) + db_printf("%p: pid %d \"%s\"\n", gd->gd_curproc, + gd->gd_curproc->p_pid, gd->gd_curproc->p_comm); + else + db_printf("none\n"); + db_printf("curpcb = %p\n", gd->gd_curpcb); + db_printf("fpcurproc = "); + if (gd->gd_fpcurproc != NULL) + db_printf("%p: pid %d \"%s\"\n", gd->gd_fpcurproc, + gd->gd_fpcurproc->p_pid, gd->gd_fpcurproc->p_comm); + else + db_printf("none\n"); + db_printf("idleproc = "); + if (gd->gd_idleproc != NULL) + db_printf("%p: pid %d \"%s\"\n", gd->gd_idleproc, + gd->gd_idleproc->p_pid, gd->gd_idleproc->p_comm); + else + db_printf("none\n"); #ifdef WITNESS - db_printf("spin locks held:\n"); - witness_list_locks(&gd->gd_spinlocks); + db_printf("spin locks held:\n"); + witness_list_locks(&gd->gd_spinlocks); #endif - } } diff --git a/sys/alpha/alpha/interrupt.c b/sys/alpha/alpha/interrupt.c index 346b21c..b28b53d 100644 --- a/sys/alpha/alpha/interrupt.c +++ b/sys/alpha/alpha/interrupt.c @@ -52,6 +52,7 @@ #include <sys/kthread.h> #include <sys/ktr.h> #include <sys/mutex.h> +#include <sys/smp.h> #include <sys/unistd.h> #include <machine/reg.h> @@ -83,7 +84,7 @@ void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf; static u_int schedclk2; -static driver_intr_t alpha_clock_interrupt; +static void alpha_clock_interrupt(struct trapframe *framep); void interrupt(a0, a1, a2, framep) @@ -453,7 +454,7 @@ alpha_dispatch_intr(void *frame, unsigned long vector) } static void -alpha_clock_interrupt(void *framep) +alpha_clock_interrupt(struct trapframe *framep) { cnt.v_intr++; @@ -462,10 +463,26 @@ alpha_clock_interrupt(void *framep) #else intrcnt[INTRCNT_CLOCK]++; #endif - if (platform.clockintr){ - (*platform.clockintr)((struct trapframe *)framep); - /* divide hz (1024) by 8 to get stathz (128) */ - if((++schedclk2 & 0x7) == 0) - statclock((struct clockframe *)framep); + if (platform.clockintr) { +#ifdef SMP + /* + * Only one processor drives the actual timer. + */ + if (PCPU_GET(cpuid) == boot_cpu_id) { +#endif + (*platform.clockintr)(framep); + /* divide hz (1024) by 8 to get stathz (128) */ + if ((++schedclk2 & 0x7) == 0) + statclock((struct clockframe *)framep); +#ifdef SMP + } else { + mtx_lock_spin(&sched_lock); + hardclock_process(curproc, TRAPF_USERMODE(framep)); + if ((schedclk2 & 0x7) == 0) + statclock_process(curproc, TRAPF_PC(framep), + TRAPF_USERMODE(framep)); + mtx_unlock_spin(&sched_lock); + } +#endif } } diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index f623669..177fe8e 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -112,6 +112,7 @@ #include <sys/vmmeter.h> #include <sys/msgbuf.h> #include <sys/exec.h> +#include <sys/smp.h> #include <sys/sysctl.h> #include <sys/uio.h> #include <sys/linker.h> @@ -130,7 +131,6 @@ #include <machine/reg.h> #include <machine/fpu.h> #include <machine/pal.h> -#include <machine/smp.h> #include <machine/globaldata.h> #include <machine/cpuconf.h> #include <machine/bootinfo.h> @@ -152,8 +152,6 @@ struct platform platform; alpha_chipset_t chipset; struct bootinfo_kernel bootinfo; -struct cpuhead cpuhead; - struct mtx sched_lock; struct mtx Giant; @@ -415,14 +413,6 @@ again: vm_pager_bufferinit(); EVENTHANDLER_REGISTER(shutdown_final, alpha_srm_shutdown, 0, SHUTDOWN_PRI_LAST); - -#ifdef SMP - /* - * OK, enough kmem_alloc/malloc state should be up, lets get on with it! - */ - mp_start(); /* fire up the secondaries */ - mp_announce(); -#endif /* SMP */ } /* @@ -1002,12 +992,6 @@ alpha_init(pfn, ptb, bim, bip, biv) */ globalp->gd_idlepcb.apcb_ptbr = proc0.p_addr->u_pcb.pcb_hw.apcb_ptbr; - /* - * Record all cpus in a list. - */ - SLIST_INIT(&cpuhead); - SLIST_INSERT_HEAD(&cpuhead, GLOBALP, gd_allcpu); - /* Setup curproc so that mutexes work */ PCPU_SET(curproc, &proc0); PCPU_SET(spinlocks, NULL); diff --git a/sys/alpha/alpha/mp_machdep.c b/sys/alpha/alpha/mp_machdep.c index 3715c2f..3024102 100644 --- a/sys/alpha/alpha/mp_machdep.c +++ b/sys/alpha/alpha/mp_machdep.c @@ -35,6 +35,7 @@ #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/kernel.h> +#include <sys/smp.h> #include <sys/sysctl.h> #include <vm/vm.h> @@ -43,55 +44,18 @@ #include <sys/user.h> #include <sys/dkstat.h> -#include <machine/smp.h> #include <machine/atomic.h> #include <machine/globaldata.h> #include <machine/pmap.h> #include <machine/rpb.h> #include <machine/clock.h> -#define CHECKSTATE_USER 0 -#define CHECKSTATE_SYS 1 -#define CHECKSTATE_INTR 2 - -volatile u_int stopped_cpus; -volatile u_int started_cpus; -volatile u_int checkstate_probed_cpus; -volatile u_int checkstate_need_ast; - /* Set to 1 once we're ready to let the APs out of the pen. */ static volatile int aps_ready = 0; static struct mtx ap_boot_mtx; -struct proc* checkstate_curproc[MAXCPU]; -int checkstate_cpustate[MAXCPU]; -u_long checkstate_pc[MAXCPU]; -volatile u_int resched_cpus; -void (*cpustop_restartfunc) __P((void)); -int mp_ncpus; - -volatile int smp_started; -int boot_cpu_id; -u_int32_t all_cpus; - -static struct globaldata *cpuid_to_globaldata[MAXCPU]; - -int smp_active = 0; /* are the APs allowed to run? */ -SYSCTL_INT(_machdep, OID_AUTO, smp_active, CTLFLAG_RW, &smp_active, 0, ""); - -static int smp_cpus = 1; /* how many cpu's running */ -SYSCTL_INT(_machdep, OID_AUTO, smp_cpus, CTLFLAG_RD, &smp_cpus, 0, ""); - -/* Enable forwarding of a signal to a process running on a different CPU */ -static int forward_signal_enabled = 1; -SYSCTL_INT(_machdep, OID_AUTO, forward_signal_enabled, CTLFLAG_RW, - &forward_signal_enabled, 0, ""); - -/* Enable forwarding of roundrobin to all other cpus */ -static int forward_roundrobin_enabled = 1; -SYSCTL_INT(_machdep, OID_AUTO, forward_roundrobin_enabled, CTLFLAG_RW, - &forward_roundrobin_enabled, 0, ""); +u_int boot_cpu_id; /* * Communicate with a console running on a secondary processor. @@ -225,7 +189,6 @@ smp_init_secondary(void) if (smp_cpus == mp_ncpus) { smp_started = 1; smp_active = 1; - ipi_all(0); } mtx_unlock_spin(&ap_boot_mtx); @@ -250,7 +213,7 @@ static int smp_start_secondary(int cpuid) { struct pcs *cpu = LOCATE_PCS(hwrpb, cpuid); - struct pcs *bootcpu = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id); + struct pcs *bootcpu = LOCATE_PCS(hwrpb, boot_cpu_id); struct alpha_pcb *pcb = (struct alpha_pcb *) cpu->pcs_hwpcb; struct globaldata *globaldata; int i; @@ -272,7 +235,6 @@ smp_start_secondary(int cpuid) } globaldata_init(globaldata, cpuid, sz); - SLIST_INSERT_HEAD(&cpuhead, globaldata, gd_allcpu); /* * Copy the idle pcb and setup the address to start executing. @@ -329,48 +291,53 @@ smp_start_secondary(int cpuid) return 1; } -/* - * Register a struct globaldata. - */ -void -globaldata_register(struct globaldata *globaldata) -{ - cpuid_to_globaldata[globaldata->gd_cpuid] = globaldata; -} +/* Other stuff */ -struct globaldata * -globaldata_find(int cpuid) +int +cpu_mp_probe(void) { - return cpuid_to_globaldata[cpuid]; -} - -/* Other stuff */ + struct pcs *pcsp; + int i, cpus; -/* lock around the MP rendezvous */ -static struct mtx smp_rv_mtx; + /* XXX: Need to check for valid platforms here. */ -static void -init_locks(void) -{ - mtx_init(&smp_rv_mtx, "smp rendezvous", MTX_SPIN); - mtx_init(&ap_boot_mtx, "ap boot", MTX_SPIN); + /* Make sure we have at least one secondary CPU. */ + cpus = 0; + for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { + if (i == PCPU_GET(cpuid)) + continue; + pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + + (i * hwrpb->rpb_pcs_size)); + if ((pcsp->pcs_flags & PCS_PP) == 0) + continue; + if ((pcsp->pcs_flags & PCS_PA) == 0) + continue; + if ((pcsp->pcs_flags & PCS_PV) == 0) + continue; + if (i > MAXCPU) + continue; + cpus++; + } + return (cpus); } void -mp_start() +cpu_mp_start() { int i; - int cpuid = PCPU_GET(cpuid); - init_locks(); + mtx_init(&ap_boot_mtx, "ap boot", MTX_SPIN); mp_ncpus = 1; - all_cpus = 1 << cpuid; + boot_cpu_id = PCPU_GET(cpuid); + KASSERT(boot_cpu_id == hwrpb->rpb_primary_cpu_id, + ("mp_start() called on non-primary CPU")); + all_cpus = 1 << boot_cpu_id; for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { struct pcs *pcsp; - if (i == cpuid) + if (i == boot_cpu_id) continue; pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + (i * hwrpb->rpb_pcs_size)); @@ -397,10 +364,10 @@ mp_start() all_cpus |= 1 << i; mp_ncpus++; } - PCPU_SET(other_cpus, all_cpus & ~(1<<cpuid)); + PCPU_SET(other_cpus, all_cpus & ~(1 << boot_cpu_id)); for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { - if (i == cpuid) + if (i == boot_cpu_id) continue; if (all_cpus & 1 << i) smp_start_secondary(i); @@ -408,561 +375,8 @@ mp_start() } void -mp_announce() -{ - - printf("SMP System Detected: %d usable CPUs\n", mp_ncpus); -} - -void -smp_invltlb() -{ -} - -#if 0 -#define GD_TO_INDEX(pc, prof) \ - ((int)(((u_quad_t)((pc) - (prof)->pr_off) * \ - (u_quad_t)((prof)->pr_scale)) >> 16) & ~1) - -static void -addupc_intr_forwarded(struct proc *p, int id, int *astmap) -{ - int i; - struct uprof *prof; - u_long pc; - - pc = checkstate_pc[id]; - prof = &p->p_stats->p_prof; - if (pc >= prof->pr_off && - (i = GD_TO_INDEX(pc, prof)) < prof->pr_size) { - if ((p->p_sflag & PS_OWEUPC) == 0) { - prof->pr_addr = pc; - prof->pr_ticks = 1; - p->p_sflag |= PS_OWEUPC; - } - *astmap |= (1 << id); - } -} - -static void -forwarded_statclock(int id, int pscnt, int *astmap) -{ - struct pstats *pstats; - long rss; - struct rusage *ru; - struct vmspace *vm; - int cpustate; - struct proc *p; -#ifdef GPROF - register struct gmonparam *g; - int i; -#endif - - p = checkstate_curproc[id]; - cpustate = checkstate_cpustate[id]; - - /* XXX */ - if (p->p_ithd) - cpustate = CHECKSTATE_INTR; - else if (p == cpuid_to_globaldata[id]->gd_idleproc) - cpustate = CHECKSTATE_SYS; - - switch (cpustate) { - case CHECKSTATE_USER: - if (p->p_sflag & PS_PROFIL) - addupc_intr_forwarded(p, id, astmap); - if (pscnt > 1) - return; - p->p_uticks++; - if (p->p_nice > NZERO) - cp_time[CP_NICE]++; - else - cp_time[CP_USER]++; - break; - case CHECKSTATE_SYS: -#ifdef GPROF - /* - * Kernel statistics are just like addupc_intr, only easier. - */ - g = &_gmonparam; - if (g->state == GMON_PROF_ON) { - i = checkstate_pc[id] - g->lowpc; - if (i < g->textsize) { - i /= HISTFRACTION * sizeof(*g->kcount); - g->kcount[i]++; - } - } -#endif - if (pscnt > 1) - return; - - p->p_sticks++; - if (p == cpuid_to_globaldata[id]->gd_idleproc) - cp_time[CP_IDLE]++; - else - cp_time[CP_SYS]++; - break; - case CHECKSTATE_INTR: - default: -#ifdef GPROF - /* - * Kernel statistics are just like addupc_intr, only easier. - */ - g = &_gmonparam; - if (g->state == GMON_PROF_ON) { - i = checkstate_pc[id] - g->lowpc; - if (i < g->textsize) { - i /= HISTFRACTION * sizeof(*g->kcount); - g->kcount[i]++; - } - } -#endif - if (pscnt > 1) - return; - KASSERT(p != NULL, ("NULL process in interrupt state")); - p->p_iticks++; - cp_time[CP_INTR]++; - } - - schedclock(p); - - /* Update resource usage integrals and maximums. */ - if ((pstats = p->p_stats) != NULL && - (ru = &pstats->p_ru) != NULL && - (vm = p->p_vmspace) != NULL) { - ru->ru_ixrss += pgtok(vm->vm_tsize); - ru->ru_idrss += pgtok(vm->vm_dsize); - ru->ru_isrss += pgtok(vm->vm_ssize); - rss = pgtok(vmspace_resident_count(vm)); - if (ru->ru_maxrss < rss) - ru->ru_maxrss = rss; - } -} - -void -forward_statclock(int pscnt) -{ - int map; - int id; - int i; - - /* Kludge. We don't yet have separate locks for the interrupts - * and the kernel. This means that we cannot let the other processors - * handle complex interrupts while inhibiting them from entering - * the kernel in a non-interrupt context. - * - * What we can do, without changing the locking mechanisms yet, - * is letting the other processors handle a very simple interrupt - * (wich determines the processor states), and do the main - * work ourself. - */ - - CTR1(KTR_SMP, "forward_statclock(%d)", pscnt); - - if (!smp_started || cold || panicstr) - return; - - /* Step 1: Probe state (user, cpu, interrupt, spinlock, idle ) */ - - mtx_lock_spin(&smp_rv_mtx); - map = PCPU_GET(other_cpus) & ~stopped_cpus ; - checkstate_probed_cpus = 0; - if (map != 0) - ipi_selected(map, IPI_CHECKSTATE); - - i = 0; - while (checkstate_probed_cpus != map) { - alpha_mb(); - /* spin */ - i++; - if (i == 100000) { -#ifdef DIAGNOSTIC - printf("forward_statclock: checkstate %x\n", - checkstate_probed_cpus); -#endif - break; - } - } - mtx_unlock_spin(&smp_rv_mtx); - - /* - * Step 2: walk through other processors processes, update ticks and - * profiling info. - */ - - map = 0; - /* XXX: wrong, should walk bits in all_cpus */ - for (id = 0; id < mp_ncpus; id++) { - if (id == PCPU_GET(cpuid)) - continue; - if (((1 << id) & checkstate_probed_cpus) == 0) - continue; - forwarded_statclock(id, pscnt, &map); - } - if (map != 0) { - mtx_lock_spin(&smp_rv_mtx); - checkstate_need_ast |= map; - ipi_selected(map, IPI_AST); - i = 0; - while ((checkstate_need_ast & map) != 0) { - alpha_mb(); - /* spin */ - i++; - if (i > 100000) { -#ifdef DIAGNOSTIC - printf("forward_statclock: dropped ast 0x%x\n", - checkstate_need_ast & map); -#endif - break; - } - } - mtx_unlock_spin(&smp_rv_mtx); - } -} - -void -forward_hardclock(int pscnt) -{ - int map; - int id; - struct proc *p; - struct pstats *pstats; - int i; - - /* Kludge. We don't yet have separate locks for the interrupts - * and the kernel. This means that we cannot let the other processors - * handle complex interrupts while inhibiting them from entering - * the kernel in a non-interrupt context. - * - * What we can do, without changing the locking mechanisms yet, - * is letting the other processors handle a very simple interrupt - * (wich determines the processor states), and do the main - * work ourself. - */ - - CTR1(KTR_SMP, "forward_hardclock(%d)", pscnt); - - if (!smp_started || cold || panicstr) - return; - - /* Step 1: Probe state (user, cpu, interrupt, spinlock, idle) */ - - mtx_lock_spin(&smp_rv_mtx); - map = PCPU_GET(other_cpus) & ~stopped_cpus ; - checkstate_probed_cpus = 0; - if (map != 0) - ipi_selected(map, IPI_CHECKSTATE); - - i = 0; - while (checkstate_probed_cpus != map) { - alpha_mb(); - /* spin */ - i++; - if (i == 100000) { -#ifdef DIAGNOSTIC - printf("forward_hardclock: checkstate %x\n", - checkstate_probed_cpus); -#endif - breakpoint(); - break; - } - } - mtx_unlock_spin(&smp_rv_mtx); - - /* - * Step 2: walk through other processors processes, update virtual - * timer and profiling timer. If stathz == 0, also update ticks and - * profiling info. - */ - - map = 0; - /* XXX: wrong, should walk bits in all_cpus */ - for (id = 0; id < mp_ncpus; id++) { - if (id == PCPU_GET(cpuid)) - continue; - if (((1 << id) & checkstate_probed_cpus) == 0) - continue; - p = checkstate_curproc[id]; - if (p) { - pstats = p->p_stats; - if (checkstate_cpustate[id] == CHECKSTATE_USER && - timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) && - itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) { - p->p_sflag |= PS_ALRMPEND; - map |= (1 << id); - } - if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) && - itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) { - p->p_sflag |= PS_PROFPEND; - map |= (1 << id); - } - } - if (stathz == 0) { - forwarded_statclock( id, pscnt, &map); - } - } - if (map != 0) { - mtx_lock_spin(&smp_rv_mtx); - checkstate_need_ast |= map; - ipi_selected(map, IPI_AST); - i = 0; - while ((checkstate_need_ast & map) != 0) { - alpha_mb(); - /* spin */ - i++; - if (i > 100000) { -#ifdef DIAGNOSTIC - printf("forward_hardclock: dropped ast 0x%x\n", - checkstate_need_ast & map); -#endif - break; - } - } - mtx_unlock_spin(&smp_rv_mtx); - } -} -#endif /* 0 */ - -void -forward_signal(struct proc *p) -{ - int map; - int id; - int i; - - /* Kludge. We don't yet have separate locks for the interrupts - * and the kernel. This means that we cannot let the other processors - * handle complex interrupts while inhibiting them from entering - * the kernel in a non-interrupt context. - * - * What we can do, without changing the locking mechanisms yet, - * is letting the other processors handle a very simple interrupt - * (wich determines the processor states), and do the main - * work ourself. - */ - - CTR1(KTR_SMP, "forward_signal(%p)", p); - - if (!smp_started || cold || panicstr) - return; - if (!forward_signal_enabled) - return; - mtx_lock_spin(&sched_lock); - while (1) { - if (p->p_stat != SRUN) { - mtx_unlock_spin(&sched_lock); - return; - } - id = p->p_oncpu; - mtx_unlock_spin(&sched_lock); - if (id == 0xff) - return; - map = (1<<id); - checkstate_need_ast |= map; - ipi_selected(map, IPI_AST); - i = 0; - while ((checkstate_need_ast & map) != 0) { - alpha_mb(); - /* spin */ - i++; - if (i > 100000) { -#if DIAGNOSTIC - printf("forward_signal: dropped ast 0x%x\n", - checkstate_need_ast & map); -#endif - break; - } - } - mtx_lock_spin(&sched_lock); - if (id == p->p_oncpu) { - mtx_unlock_spin(&sched_lock); - return; - } - } -} - -void -forward_roundrobin(void) -{ - u_int map; - int i; - - CTR0(KTR_SMP, "forward_roundrobin()"); - - if (!smp_started || cold || panicstr) - return; - if (!forward_roundrobin_enabled) - return; - resched_cpus |= PCPU_GET(other_cpus); - map = PCPU_GET(other_cpus) & ~stopped_cpus ; - ipi_selected(map, IPI_AST); - i = 0; - while ((checkstate_need_ast & map) != 0) { - alpha_mb(); - /* spin */ - i++; - if (i > 100000) { -#if DIAGNOSTIC - printf("forward_roundrobin: dropped ast 0x%x\n", - checkstate_need_ast & map); -#endif - break; - } - } -} - -/* - * When called the executing CPU will send an IPI to all other CPUs - * requesting that they halt execution. - * - * Usually (but not necessarily) called with 'other_cpus' as its arg. - * - * - Signals all CPUs in map to stop. - * - Waits for each to stop. - * - * Returns: - * -1: error - * 0: NA - * 1: ok - * - * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs - * from executing at same time. - */ -int -stop_cpus(u_int map) -{ - int i; - - if (!smp_started) - return 0; - - CTR1(KTR_SMP, "stop_cpus(%x)", map); - - /* send the stop IPI to all CPUs in map */ - ipi_selected(map, IPI_STOP); - - i = 0; - while ((stopped_cpus & map) != map) { - /* spin */ - i++; -#ifdef DIAGNOSTIC - if (i == 100000) { - printf("timeout stopping cpus\n"); - break; - } -#endif - alpha_mb(); - } - - return 1; -} - - -/* - * Called by a CPU to restart stopped CPUs. - * - * Usually (but not necessarily) called with 'stopped_cpus' as its arg. - * - * - Signals all CPUs in map to restart. - * - Waits for each to restart. - * - * Returns: - * -1: error - * 0: NA - * 1: ok - */ -int -restart_cpus(u_int map) -{ - if (!smp_started) - return 0; - - CTR1(KTR_SMP, "restart_cpus(%x)", map); - - started_cpus = map; /* signal other cpus to restart */ - alpha_mb(); - - while ((stopped_cpus & map) != 0) /* wait for each to clear its bit */ - alpha_mb(); - - return 1; -} - -/* - * All-CPU rendezvous. CPUs are signalled, all execute the setup function - * (if specified), rendezvous, execute the action function (if specified), - * rendezvous again, execute the teardown function (if specified), and then - * resume. - * - * Note that the supplied external functions _must_ be reentrant and aware - * that they are running in parallel and in an unknown lock context. - */ -static void (*smp_rv_setup_func)(void *arg); -static void (*smp_rv_action_func)(void *arg); -static void (*smp_rv_teardown_func)(void *arg); -static void *smp_rv_func_arg; -static volatile int smp_rv_waiters[2]; - -void -smp_rendezvous_action(void) +cpu_mp_announce() { - /* setup function */ - if (smp_rv_setup_func != NULL) - smp_rv_setup_func(smp_rv_func_arg); - /* spin on entry rendezvous */ - atomic_add_int(&smp_rv_waiters[0], 1); - while (smp_rv_waiters[0] < mp_ncpus) - alpha_mb(); - /* action function */ - if (smp_rv_action_func != NULL) - smp_rv_action_func(smp_rv_func_arg); - /* spin on exit rendezvous */ - atomic_add_int(&smp_rv_waiters[1], 1); - while (smp_rv_waiters[1] < mp_ncpus) - alpha_mb(); - /* teardown function */ - if (smp_rv_teardown_func != NULL) - smp_rv_teardown_func(smp_rv_func_arg); -} - -void -smp_rendezvous(void (* setup_func)(void *), - void (* action_func)(void *), - void (* teardown_func)(void *), - void *arg) -{ - - if (!smp_started) { - if (setup_func != NULL) - setup_func(arg); - if (action_func != NULL) - action_func(arg); - if (teardown_func != NULL) - teardown_func(arg); - return; - } - - /* obtain rendezvous lock */ - mtx_lock_spin(&smp_rv_mtx); - - /* set static function pointers */ - smp_rv_setup_func = setup_func; - smp_rv_action_func = action_func; - smp_rv_teardown_func = teardown_func; - smp_rv_func_arg = arg; - smp_rv_waiters[0] = 0; - smp_rv_waiters[1] = 0; - - /* signal other processors, which will enter the IPI with interrupts off */ - ipi_all_but_self(IPI_RENDEZVOUS); - - /* call executor function */ - CTR2(KTR_SMP, "smp_rv: calling action = %p, arg = %p\n", action_func, - arg); - smp_rendezvous_action(); - - /* release lock */ - mtx_unlock_spin(&smp_rv_mtx); } /* @@ -979,7 +393,7 @@ ipi_selected(u_int32_t cpus, u_int64_t ipi) int cpuid = ffs(cpus) - 1; cpus &= ~(1 << cpuid); - globaldata = cpuid_to_globaldata[cpuid]; + globaldata = globaldata_find(cpuid); if (globaldata) { atomic_set_64(&globaldata->gd_pending_ipis, ipi); alpha_mb(); @@ -1048,25 +462,6 @@ smp_handle_ipi(struct trapframe *frame) case IPI_AST: CTR0(KTR_SMP, "IPI_AST"); - atomic_clear_int(&checkstate_need_ast, cpumask); - mtx_lock_spin(&sched_lock); - curproc->p_sflag |= PS_ASTPENDING; - mtx_unlock_spin(&sched_lock); - break; - - case IPI_CHECKSTATE: - CTR0(KTR_SMP, "IPI_CHECKSTATE"); - if (frame->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) - checkstate_cpustate[PCPU_GET(cpuid)] = - CHECKSTATE_USER; - else if (curproc->p_intr_nesting_level == 1) - checkstate_cpustate[PCPU_GET(cpuid)] = - CHECKSTATE_SYS; - else - checkstate_cpustate[PCPU_GET(cpuid)] = - CHECKSTATE_INTR; - checkstate_curproc[PCPU_GET(cpuid)] = curproc; - atomic_set_int(&checkstate_probed_cpus, cpumask); break; case IPI_STOP: @@ -1085,7 +480,7 @@ smp_handle_ipi(struct trapframe *frame) * requests to provide PALcode to secondaries and to start up new * secondaries that are added to the system on the fly. */ - if (PCPU_GET(cpuid) == hwrpb->rpb_primary_cpu_id) { + if (PCPU_GET(cpuid) == boot_cpu_id) { u_int cpuid; u_int64_t txrdy; #ifdef DIAGNOSTIC diff --git a/sys/alpha/alpha/pmap.c b/sys/alpha/alpha/pmap.c index d7fe3df..f70bd00 100644 --- a/sys/alpha/alpha/pmap.c +++ b/sys/alpha/alpha/pmap.c @@ -154,6 +154,7 @@ #include <sys/msgbuf.h> #include <sys/vmmeter.h> #include <sys/mman.h> +#include <sys/smp.h> #include <sys/sx.h> #include <vm/vm.h> @@ -172,7 +173,6 @@ #include <machine/md_var.h> #include <machine/rpb.h> -#include <machine/smp.h> #ifndef PMAP_SHPGPERPROC #define PMAP_SHPGPERPROC 200 diff --git a/sys/alpha/alpha/trap.c b/sys/alpha/alpha/trap.c index 228c50b..7238e7a 100644 --- a/sys/alpha/alpha/trap.c +++ b/sys/alpha/alpha/trap.c @@ -42,6 +42,7 @@ #include <sys/exec.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/smp.h> #include <sys/vmmeter.h> #include <sys/sysent.h> #include <sys/syscall.h> @@ -59,7 +60,6 @@ #include <machine/reg.h> #include <machine/pal.h> #include <machine/fpu.h> -#include <machine/smp.h> #ifdef KTRACE #include <sys/uio.h> @@ -150,7 +150,7 @@ userret(p, frame, oticks) mtx_lock_spin(&sched_lock); p->p_pri.pri_level = p->p_pri.pri_user; - if (resched_wanted()) { + if (resched_wanted(p)) { /* * Since we are curproc, a clock interrupt could * change our priority without changing run queues @@ -877,7 +877,7 @@ ast(framep) * acquiring and releasing mutexes in assembly is not fun. */ mtx_lock_spin(&sched_lock); - if (!(astpending(p) || resched_wanted())) { + if (!(astpending(p) || resched_wanted(p))) { mtx_unlock_spin(&sched_lock); return; } diff --git a/sys/alpha/include/cpu.h b/sys/alpha/include/cpu.h index d8ff1cc..f3bd8d2 100644 --- a/sys/alpha/include/cpu.h +++ b/sys/alpha/include/cpu.h @@ -68,7 +68,6 @@ struct clockframe { #define CLKF_USERMODE(framep) TRAPF_USERMODE(&(framep)->cf_tf) #define CLKF_PC(framep) TRAPF_PC(&(framep)->cf_tf) -#define CLKF_INTR(framep) (curproc->p_intr_nesting_level >= 2) /* * Arrange to handle pending profiling ticks before returning to user mode. diff --git a/sys/alpha/include/globaldata.h b/sys/alpha/include/globaldata.h index 15bd8c41a..4d6d02f 100644 --- a/sys/alpha/include/globaldata.h +++ b/sys/alpha/include/globaldata.h @@ -66,14 +66,7 @@ struct globaldata { #endif }; -SLIST_HEAD(cpuhead, globaldata); -extern struct cpuhead cpuhead; - void globaldata_init(struct globaldata *pcpu, int cpuid, size_t sz); -struct globaldata *globaldata_find(int cpuid); -#ifdef SMP -void globaldata_register(struct globaldata *pcpu); -#endif #endif /* _KERNEL */ diff --git a/sys/alpha/include/ipl.h b/sys/alpha/include/ipl.h index 357dc7a..9b94bf6 100644 --- a/sys/alpha/include/ipl.h +++ b/sys/alpha/include/ipl.h @@ -30,23 +30,4 @@ #define _MACHINE_IPL_H_ -#include <machine/cpu.h> /* for pal inlines */ - -#ifdef SMP -/* - * Interprocessor interrupts for SMP. - */ -#define IPI_INVLTLB 0x0001 -#define IPI_RENDEZVOUS 0x0002 -#define IPI_AST 0x0004 -#define IPI_CHECKSTATE 0x0008 -#define IPI_STOP 0x0010 - -void ipi_selected(u_int32_t cpus, u_int64_t ipi); -void ipi_all(u_int64_t ipi); -void ipi_all_but_self(u_int64_t ipi); -void ipi_self(u_int64_t ipi); -void smp_handle_ipi(struct trapframe *frame); -#endif - #endif /* !_MACHINE_IPL_H_ */ diff --git a/sys/alpha/include/pcpu.h b/sys/alpha/include/pcpu.h index 15bd8c41a..4d6d02f 100644 --- a/sys/alpha/include/pcpu.h +++ b/sys/alpha/include/pcpu.h @@ -66,14 +66,7 @@ struct globaldata { #endif }; -SLIST_HEAD(cpuhead, globaldata); -extern struct cpuhead cpuhead; - void globaldata_init(struct globaldata *pcpu, int cpuid, size_t sz); -struct globaldata *globaldata_find(int cpuid); -#ifdef SMP -void globaldata_register(struct globaldata *pcpu); -#endif #endif /* _KERNEL */ diff --git a/sys/alpha/include/smp.h b/sys/alpha/include/smp.h index 2c208c8..05af7f4 100644 --- a/sys/alpha/include/smp.h +++ b/sys/alpha/include/smp.h @@ -15,41 +15,24 @@ #ifdef _KERNEL -#include <sys/ipl.h> -#include <sys/ktr.h> -#include <sys/mutex.h> +/* + * Interprocessor interrupts for SMP. + */ +#define IPI_INVLTLB 0x0001 +#define IPI_RENDEZVOUS 0x0002 +#define IPI_AST 0x0004 +#define IPI_CHECKSTATE 0x0008 +#define IPI_STOP 0x0010 #ifndef LOCORE -#define BETTER_CLOCK /* unconditional on alpha */ - -/* global data in mp_machdep.c */ -extern volatile u_int checkstate_probed_cpus; -extern volatile u_int checkstate_need_ast; -extern volatile u_int resched_cpus; -extern void (*cpustop_restartfunc) __P((void)); - -extern int smp_active; -extern int mp_ncpus; -extern u_int all_cpus; -extern u_int started_cpus; -extern u_int stopped_cpus; +extern u_int boot_cpu_id; -/* functions in mp_machdep.c */ -void mp_start(void); -void mp_announce(void); -void smp_invltlb(void); -void forward_statclock(int pscnt); -void forward_hardclock(int pscnt); -void forward_signal(struct proc *); -void forward_roundrobin(void); -int stop_cpus(u_int); -int restart_cpus(u_int); -void smp_rendezvous_action(void); -void smp_rendezvous(void (*)(void *), - void (*)(void *), - void (*)(void *), - void *arg); +void ipi_selected(u_int cpus, u_int64_t ipi); +void ipi_all(u_int64_t ipi); +void ipi_all_but_self(u_int64_t ipi); +void ipi_self(u_int64_t ipi); +void smp_handle_ipi(struct trapframe *frame); void smp_init_secondary(void); #endif /* !LOCORE */ |