diff options
87 files changed, 1045 insertions, 4299 deletions
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c index 9a97d9b4e90..ff9b9b377a9 100644 --- a/lib/libkvm/kvm_proc.c +++ b/lib/libkvm/kvm_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kvm_proc.c,v 1.34 2007/06/18 21:51:15 pedro Exp $ */ +/* $OpenBSD: kvm_proc.c,v 1.35 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: kvm_proc.c,v 1.30 1999/03/24 05:50:50 mrg Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ #if 0 static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93"; #else -static char *rcsid = "$OpenBSD: kvm_proc.c,v 1.34 2007/06/18 21:51:15 pedro Exp $"; +static char *rcsid = "$OpenBSD: kvm_proc.c,v 1.35 2007/10/10 15:53:51 art Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -477,8 +477,6 @@ kvm_getproc2(kvm_t *kd, int op, int arg, size_t esize, int *cnt) kp2p = &kp2; for (i = 0; i < nprocs; i++, kp++) { memset(kp2p, 0, sizeof(kp2)); - kp2p->p_forw = PTRTOINT64(kp->kp_proc.p_forw); - kp2p->p_back = PTRTOINT64(kp->kp_proc.p_back); kp2p->p_paddr = PTRTOINT64(kp->kp_eproc.e_paddr); kp2p->p_addr = PTRTOINT64(kp->kp_proc.p_addr); diff --git a/sys/arch/alpha/alpha/genassym.cf b/sys/arch/alpha/alpha/genassym.cf index cddc3760215..d8393934035 100644 --- a/sys/arch/alpha/alpha/genassym.cf +++ b/sys/arch/alpha/alpha/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.10 2007/05/28 23:10:10 beck Exp $ +# $OpenBSD: genassym.cf,v 1.11 2007/10/10 15:53:51 art Exp $ # Copyright (c) 1994, 1995 Gordon W. Ross # Copyright (c) 1993 Adam Glass @@ -103,17 +103,12 @@ export ALPHA_PTE_KW # Important offsets into the proc struct & associated constants struct proc -member p_forw -member p_back member p_addr member p_vmspace member p_stat member P_MD_FLAGS p_md.md_flags member P_MD_PCBPADDR p_md.md_pcbpaddr member p_cpu -struct prochd -member ph_link -member ph_rlink export SONPROC diff --git a/sys/arch/alpha/alpha/locore.s b/sys/arch/alpha/alpha/locore.s index 6b9f238138f..fe7453cec66 100644 --- a/sys/arch/alpha/alpha/locore.s +++ b/sys/arch/alpha/alpha/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.30 2007/05/28 23:10:10 beck Exp $ */ +/* $OpenBSD: locore.s,v 1.31 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: locore.s,v 1.94 2001/04/26 03:10:44 ross Exp $ */ /*- @@ -716,123 +716,38 @@ LEAF(savectx, 1) /**************************************************************************/ -IMPORT(whichqs, 4) - -/* - * When no processes are on the runq, cpu_switch branches to idle - * to wait for something to come ready. - * Note: this is really a part of cpu_switch() but defined here for kernel - * profiling. - */ -LEAF(idle, 0) - br pv, 1f -1: LDGP(pv) - /* Note: GET_CURPROC clobbers v0, t0, t8...t11. */ - GET_CURPROC - stq zero, 0(v0) /* curproc <- NULL for stats */ -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - CALL(sched_unlock_idle) /* release sched_lock */ -#endif - mov zero, a0 /* enable all interrupts */ - call_pal PAL_OSF1_swpipl -2: ldl t0, whichqs /* look for non-empty queue */ - beq t0, 2b - ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */ - call_pal PAL_OSF1_swpipl -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - CALL(sched_lock_idle) /* acquire sched_lock */ -#endif - jmp zero, cpu_switch_queuescan /* jump back into the fire */ - END(idle) - /* - * cpu_switch() - * Find the highest priority process and resume it. + * cpu_switchto(struct proc *old, struct proc *new) + * Switch from "old" proc to "new". */ -LEAF(cpu_switch, 0) +LEAF(cpu_switchto, 2) LDGP(pv) - /* - * do an inline savectx(), to save old context - * Note: GET_CURPROC clobbers v0, t0, t8...t11. - */ - GET_CURPROC - ldq a0, 0(v0) - ldq a1, P_ADDR(a0) - /* NOTE: ksp is stored by the swpctx */ - stq s0, U_PCB_CONTEXT+(0 * 8)(a1) /* store s0 - s6 */ - stq s1, U_PCB_CONTEXT+(1 * 8)(a1) - stq s2, U_PCB_CONTEXT+(2 * 8)(a1) - stq s3, U_PCB_CONTEXT+(3 * 8)(a1) - stq s4, U_PCB_CONTEXT+(4 * 8)(a1) - stq s5, U_PCB_CONTEXT+(5 * 8)(a1) - stq s6, U_PCB_CONTEXT+(6 * 8)(a1) - stq ra, U_PCB_CONTEXT+(7 * 8)(a1) /* store ra */ - call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */ - stq v0, U_PCB_CONTEXT+(8 * 8)(a1) /* store ps, for ipl */ - mov a0, s0 /* save old curproc */ - mov a1, s1 /* save old U-area */ - -cpu_switch_queuescan: - br pv, 1f -1: LDGP(pv) - ldl t0, whichqs /* look for non-empty queue */ - beq t0, idle /* and if none, go idle */ - mov t0, t3 /* t3 = saved whichqs */ - mov zero, t2 /* t2 = lowest bit set */ - blbs t0, 3f /* if low bit set, done! */ - -2: srl t0, 1, t0 /* try next bit */ - addq t2, 1, t2 - blbc t0, 2b /* if clear, try again */ - -3: /* - * Remove process from queue - */ - lda t1, qs /* get queues */ - sll t2, 4, t0 /* queue head is 16 bytes */ - addq t1, t0, t0 /* t0 = qp = &qs[firstbit] */ - - ldq t4, PH_LINK(t0) /* t4 = p = highest pri proc */ - bne t4, 4f /* make sure p != NULL */ - PANIC("cpu_switch",Lcpu_switch_pmsg) /* nothing in queue! */ - -4: - ldq t5, P_FORW(t4) /* t5 = p->p_forw */ - stq t5, PH_LINK(t0) /* qp->ph_link = p->p_forw */ - stq t0, P_BACK(t5) /* p->p_forw->p_back = qp */ - stq zero, P_BACK(t4) /* firewall: p->p_back = NULL */ - cmpeq t0, t5, t0 /* see if queue is empty */ - beq t0, 5f /* nope, it's not! */ - - ldiq t0, 1 /* compute bit in whichqs */ - sll t0, t2, t0 - xor t3, t0, t3 /* clear bit in whichqs */ - stl t3, whichqs - -5: - mov t4, s2 /* save new proc */ - ldq s3, P_MD_PCBPADDR(s2) /* save new pcbpaddr */ -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) /* - * Done mucking with the run queues, release the - * scheduler lock, but keep interrupts out. + * Don't bother saving the old context if oldproc is NULL. */ - CALL(sched_unlock_idle) -#endif + beq a0, 1f /* - * Check to see if we're switching to ourself. If we are, - * don't bother loading the new context. - * - * Note that even if we re-enter cpu_switch() from idle(), - * s0 will still contain the old curproc value because any - * users of that register between then and now must have - * saved it. Also note that switch_exit() ensures that - * s0 is clear before jumping here to find a new process. + * do an inline savectx(), to save old context */ - cmpeq s0, s2, t0 /* oldproc == newproc? */ - bne t0, 7f /* Yes! Skip! */ + call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */ + ldq t0, P_ADDR(a0) + /* NOTE: ksp is stored by the swpctx */ + stq s0, U_PCB_CONTEXT+(0 * 8)(t0) /* store s0 - s6 */ + stq s1, U_PCB_CONTEXT+(1 * 8)(t0) + stq s2, U_PCB_CONTEXT+(2 * 8)(t0) + stq s3, U_PCB_CONTEXT+(3 * 8)(t0) + stq s4, U_PCB_CONTEXT+(4 * 8)(t0) + stq s5, U_PCB_CONTEXT+(5 * 8)(t0) + stq s6, U_PCB_CONTEXT+(6 * 8)(t0) + stq ra, U_PCB_CONTEXT+(7 * 8)(t0) /* store ra */ + stq v0, U_PCB_CONTEXT+(8 * 8)(t0) /* store ps, for ipl */ + +1: + mov a0, s0 /* save old proc */ + mov a1, s2 /* save new proc */ + ldq s3, P_MD_PCBPADDR(s2) /* save new pcbpaddr */ /* * Deactivate the old address space before activating the @@ -842,18 +757,18 @@ cpu_switch_queuescan: * do this after we activate, then we might end up * incorrectly marking the pmap inactive! * - * We don't deactivate if we came here from switch_exit + * We don't deactivate if we came here from sched_exit * (old pmap no longer exists; vmspace has been freed). * oldproc will be NULL in this case. We have actually * taken care of calling pmap_deactivate() in cpu_exit(), * before the vmspace went away. */ - beq s0, 6f + beq s0, 2f mov s0, a0 /* pmap_deactivate(oldproc) */ CALL(pmap_deactivate) -6: /* +2: /* * Activate the new process's address space and perform * the actual context swap. */ @@ -864,7 +779,7 @@ cpu_switch_queuescan: mov s3, a0 /* swap the context */ SWITCH_CONTEXT -7: /* + /* * Now that the switch is done, update curproc and other * globals. We must do this even if switching to ourselves * because we might have re-entered cpu_switch() from idle(), @@ -911,7 +826,7 @@ EXPORT(__bwx_switch1) ldiq v0, 1 /* possible ret to savectx() */ RET - END(cpu_switch) + END(cpu_switchto) #ifndef SMALL_KERNEL /* @@ -926,6 +841,18 @@ EXPORT(__bwx_switch2) EXPORT(__bwx_switch3) #endif +LEAF(cpu_idle_enter, 0) + RET + END(cpu_idle_enter) + +LEAF(cpu_idle_cycle, 0) + RET + END(cpu_idle_cycle) + +LEAF(cpu_idle_leave, 0) + RET + END(cpu_idle_leave) + /* * switch_trampoline() * @@ -945,46 +872,6 @@ LEAF(switch_trampoline, 0) jmp zero, (pv) END(switch_trampoline) -/* - * switch_exit(struct proc *p) - * Make a the named process exit. Partially switch to our idle thread - * (we don't update curproc or restore registers), and jump into the middle - * of cpu_switch to switch into a few process. The process reaper will - * free the dead process's VM resources. MUST BE CALLED AT SPLHIGH. - */ -LEAF(switch_exit, 1) - LDGP(pv) - - /* save the exiting proc pointer */ - mov a0, s2 - - /* Switch to our idle stack. */ - GET_IDLE_PCB(a0) /* clobbers v0, t0, t8-t11 */ - SWITCH_CONTEXT - - /* - * Now running as idle thread, except for the value of 'curproc' and - * the saved regs. - */ - - /* Schedule the vmspace and stack to be freed. */ - mov s2, a0 - CALL(exit2) - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - CALL(sched_lock_idle) /* acquire sched_lock */ -#endif - - /* - * Now jump back into the middle of cpu_switch(). Note that - * we must clear s0 to guarantee that the check for switching - * to ourselves in cpu_switch() will fail. This is safe since - * s0 will be restored when a new process is resumed. - */ - mov zero, s0 - jmp zero, cpu_switch_queuescan - END(switch_exit) - /**************************************************************************/ /* diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c index ce9d237b8d8..4f7836c9de1 100644 --- a/sys/arch/alpha/alpha/machdep.c +++ b/sys/arch/alpha/alpha/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.112 2007/09/15 10:10:37 martin Exp $ */ +/* $OpenBSD: machdep.c,v 1.113 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */ /*- @@ -1874,66 +1874,6 @@ spl0() } /* - * The following primitives manipulate the run queues. _whichqs tells which - * of the 32 queues _qs have processes in them. Setrunqueue puts processes - * into queues, Remrunqueue removes them from queues. The running process is - * on no queue, other processes are on a queue related to p->p_priority, - * divided by 4 actually to shrink the 0-127 range of priorities into the 32 - * available queues. - */ -/* - * setrunqueue(p) - * proc *p; - * - * Call should be made at splclock(), and p->p_stat should be SRUN. - */ - -/* XXXART - grmble */ -#define sched_qs qs -#define sched_whichqs whichqs - -void -setrunqueue(p) - struct proc *p; -{ - int bit; - - /* firewall: p->p_back must be NULL */ - if (p->p_back != NULL) - panic("setrunqueue"); - - bit = p->p_priority >> 2; - sched_whichqs |= (1 << bit); - p->p_forw = (struct proc *)&sched_qs[bit]; - p->p_back = sched_qs[bit].ph_rlink; - p->p_back->p_forw = p; - sched_qs[bit].ph_rlink = p; -} - -/* - * remrunqueue(p) - * - * Call should be made at splclock(). - */ -void -remrunqueue(p) - struct proc *p; -{ - int bit; - - bit = p->p_priority >> 2; - if ((sched_whichqs & (1 << bit)) == 0) - panic("remrunqueue"); - - p->p_back->p_forw = p->p_forw; - p->p_forw->p_back = p->p_back; - p->p_back = NULL; /* for firewall checking. */ - - if ((struct proc *)&sched_qs[bit] == sched_qs[bit].ph_link) - sched_whichqs &= ~(1 << bit); -} - -/* * Wait "n" microseconds. */ void diff --git a/sys/arch/alpha/alpha/vm_machdep.c b/sys/arch/alpha/alpha/vm_machdep.c index 16191729b90..eda0437fb46 100644 --- a/sys/arch/alpha/alpha/vm_machdep.c +++ b/sys/arch/alpha/alpha/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.34 2007/09/03 01:24:22 krw Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.35 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.55 2000/03/29 03:49:48 simonb Exp $ */ /* @@ -114,9 +114,7 @@ cpu_exit(p) * vmspace's context until the switch to proc0 in switch_exit(). */ pmap_deactivate(p); - - (void) splhigh(); - switch_exit(p); + sched_exit(p); /* NOTREACHED */ } diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c index 2f29892d219..554a62ef344 100644 --- a/sys/arch/amd64/amd64/cpu.c +++ b/sys/arch/amd64/amd64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.14 2007/09/17 15:34:38 chl Exp $ */ +/* $OpenBSD: cpu.c,v 1.15 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */ /*- @@ -345,6 +345,7 @@ cpu_attach(struct device *parent, struct device *self, void *aux) #if defined(MULTIPROCESSOR) cpu_intr_init(ci); gdt_alloc_cpu(ci); + sched_init_cpu(ci); cpu_start_secondary(ci); ncpus++; if (ci->ci_flags & CPUF_PRESENT) { @@ -540,6 +541,9 @@ cpu_hatch(void *v) microuptime(&ci->ci_schedstate.spc_runtime); splx(s); + + SCHED_LOCK(s); + cpu_switchto(NULL, sched_chooseproc()); } #if defined(DDB) diff --git a/sys/arch/amd64/amd64/genassym.cf b/sys/arch/amd64/amd64/genassym.cf index 1632d9b7c8f..f591049c3dc 100644 --- a/sys/arch/amd64/amd64/genassym.cf +++ b/sys/arch/amd64/amd64/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.14 2007/06/01 21:01:51 art Exp $ +# $OpenBSD: genassym.cf,v 1.15 2007/10/10 15:53:51 art Exp $ # Written by Artur Grabowski art@openbsd.org, Public Domain include <sys/param.h> @@ -33,8 +33,6 @@ define UVM_PAGE_IDLE_ZERO offsetof(struct uvm, page_idle_zero) struct proc member p_addr -member p_back -member p_forw member p_priority member p_stat member p_wchan diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S index e44923662e8..7a382441870 100644 --- a/sys/arch/amd64/amd64/locore.S +++ b/sys/arch/amd64/amd64/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.23 2007/09/12 18:18:27 deraadt Exp $ */ +/* $OpenBSD: locore.S,v 1.24 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ /* @@ -723,13 +723,8 @@ ENTRY(longjmp) * actually to shrink the 0-127 range of priorities into the 32 available * queues. */ - .globl _C_LABEL(whichqs),_C_LABEL(qs) .globl _C_LABEL(uvmexp),_C_LABEL(panic) -#if NAPM > 0 - .globl _C_LABEL(apm_cpu_idle),_C_LABEL(apm_cpu_busy) -#endif - #ifdef DIAGNOSTIC NENTRY(switch_error1) movabsq $1f,%rdi @@ -749,12 +744,10 @@ NENTRY(switch_error3) #endif /* DIAGNOSTIC */ /* - * int cpu_switch(struct proc *) - * Find a runnable process and switch to it. Wait if necessary. If the new - * proc is the same as the old one, we short-circuit the context save and - * restore. + * int cpu_switchto(struct proc *old, struct proc *new) + * Switch from "old" proc to "new". */ -ENTRY(cpu_switch) +ENTRY(cpu_switchto) pushq %rbx pushq %rbp pushq %r12 @@ -762,163 +755,12 @@ ENTRY(cpu_switch) pushq %r14 pushq %r15 - movq %rdi,%r13 - - /* - * Clear curproc so that we don't accumulate system time while idle. - * This also insures that schedcpu() will move the old proc to - * the correct queue if it happens to get called from the spllower() - * below and changes the priority. (See corresponding comment in - * userret()). - */ - movq $0,CPUVAR(CURPROC) - - - /* - * First phase: find new proc. - * - * Registers: - * %rax - queue head, scratch, then zero - * %r8 - queue number - * %ecx - cached value of whichqs - * %rdx - next process in queue - * %r13 - old proc - * %r12 - new proc - */ - - /* Look for new proc. */ - cli # splhigh doesn't do a cli - movl _C_LABEL(whichqs)(%rip),%ecx - bsfl %ecx,%r8d # find a full q - jnz switch_dequeue - - /* - * idling: save old context - * - * Registers: - * %rax, %rcx - scratch - * %r13 - old proc, then old pcb - * %r12 - idle pcb - */ - - /* old proc still in %rdi */ - call _C_LABEL(pmap_deactivate) - - movq P_ADDR(%r13),%r13 - - /* Save stack pointers */ - - movq %rsp,PCB_RSP(%r13) - movq %rbp,PCB_RBP(%r13) - - /* Find idle PCB for this CPU */ -#ifndef MULTIPROCESSOR - leaq _C_LABEL(proc0)(%rip),%rcx - movq P_ADDR(%rcx),%r12 - movl P_MD_TSS_SEL(%rcx),%edx -#else - movq CPUVAR(IDLE_PCB),%r12 - movl CPUVAR(IDLE_TSS_SEL),%edx -#endif - movq $0,CPUVAR(CURPROC) - - /* Restore the idle context (avoid interrupts) */ - cli - - /* Restore stack pointers. */ - movq PCB_RSP(%r12),%rsp - movq PCB_RBP(%r12),%rbp - - /* Switch address space. */ - movq PCB_CR3(%r12),%rcx - movq %rcx,%cr3 - -#ifdef MULTIPROCESSOR - movq CPUVAR(GDT),%rax -#else - movq _C_LABEL(gdtstore)(%rip),%rax -#endif - - /* Switch TSS. Reset "task busy" flag before */ - andl $~0x0200,4(%rax,%rdx, 1) - ltr %dx - - /* Restore cr0 (including FPU state). */ - movl PCB_CR0(%r12),%ecx - movq %rcx,%cr0 - - SET_CURPCB(%r12) - - xorq %r13,%r13 - sti -idle_unlock: -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_unlock_idle) -#endif - /* Interrupts are okay again. */ - movl $IPL_NONE,%edi - call _C_LABEL(Xspllower) - jmp idle_start -idle_zero: - sti - call _C_LABEL(uvm_pageidlezero) - cli - cmpl $0,_C_LABEL(whichqs)(%rip) - jnz idle_exit -idle_loop: -#if NPCTR > 0 - incq _C_LABEL(pctr_idlcnt) -#endif - /* Try to zero some pages. */ - movl _C_LABEL(uvm)+UVM_PAGE_IDLE_ZERO(%rip),%ecx - testl %ecx,%ecx - jnz idle_zero - sti - hlt -NENTRY(mpidle) -idle_start: - cli - cmpl $0,_C_LABEL(whichqs)(%rip) - jz idle_loop -idle_exit: - movl $IPL_HIGH,CPUVAR(ILEVEL) - sti -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_lock_idle) -#endif -switch_search: - movl _C_LABEL(whichqs)(%rip),%ecx - bsfl %ecx,%r8d - jz idle_unlock - -switch_dequeue: - - sti - movq %r8,%r9 - - shlq $4, %r9 - leaq _C_LABEL(qs)(%rip),%rax - addq %r9,%rax - /* movq (%rax),%rax */ - - movq P_FORW(%rax),%r12 # unlink from front of process q -#ifdef DIAGNOSTIC - cmpq %r12,%rax # linked to self (i.e. nothing queued)? - je _C_LABEL(switch_error1) # not possible -#endif /* DIAGNOSTIC */ - movq P_FORW(%r12),%rdx - movq %rdx,P_FORW(%rax) - movq %rax,P_BACK(%rdx) - - cmpq %rdx,%rax # q empty? - jne 3f - - btrl %r8d,%ecx # yes, clear to indicate empty - movl %ecx,_C_LABEL(whichqs)(%rip) # update q status + movq %rdi, %r13 + movq %rsi, %r12 -3: /* We just did it. */ xorq %rax,%rax movl %eax,CPUVAR(RESCHED) + switch_resume: #ifdef DIAGNOSTIC cmpq %rax,P_WCHAN(%r12) @@ -927,24 +769,16 @@ switch_resume: jne _C_LABEL(switch_error3) #endif - /* Isolate proc. XXX Is this necessary? */ - movq %rax,P_BACK(%r12) - /* Record new proc. */ movb $SONPROC,P_STAT(%r12) # p->p_stat = SONPROC SET_CURPROC(%r12,%rcx) - /* Skip context switch if same proc. */ - xorl %ebx,%ebx - cmpq %r12,%r13 - je switch_return - /* If old proc exited, don't bother. */ testq %r13,%r13 jz switch_exited /* - * Second phase: save old context. + * Save old context. * * Registers: * %rax, %rcx - scratch @@ -963,7 +797,7 @@ switch_resume: switch_exited: /* - * Third phase: restore saved context. + * Restore saved context. * * Registers: * %rax, %rcx, %rdx - scratch @@ -1020,15 +854,13 @@ switch_restored: sti switch_return: -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_unlock_idle) -#endif +#if 0 + /* Violation of lock ordering, since we're holding the sched_lock */ movl $IPL_NONE,%edi call _C_LABEL(Xspllower) movl $IPL_HIGH,CPUVAR(ILEVEL) - - movl %ebx,%eax +#endif popq %r15 popq %r14 @@ -1038,87 +870,16 @@ switch_return: popq %rbx ret -ENTRY(cpu_switchto) - pushq %rbx - pushq %rbp - pushq %r12 - pushq %r13 - pushq %r14 - pushq %r15 - - movq %rdi,%r13 - movq %rsi,%r12 - - movq $0,CPUVAR(CURPROC) - - xorq %rax,%rax - jmp switch_resume - - -/* - * void switch_exit(struct proc *l, void (*exit)(struct proc *)); - * Switch to proc0's saved context and deallocate the address space and kernel - * stack for p. Then jump into cpu_switch(), as if we were in proc0 all along. - */ - .globl _C_LABEL(proc0) -ENTRY(switch_exit) -#ifdef MULTIPROCESSOR - movq CPUVAR(IDLE_PCB),%r8 - movl CPUVAR(IDLE_TSS_SEL),%edx -#else - leaq _C_LABEL(proc0)(%rip),%r9 - movq P_ADDR(%r9),%r8 - movl P_MD_TSS_SEL(%r9),%edx -#endif - - /* In case we fault... */ - movq $0,CPUVAR(CURPROC) - - cli - - /* Restore stack pointers. */ - movq PCB_RSP(%r8),%rsp - movq PCB_RBP(%r8),%rbp - - /* Load TSS info. */ -#ifdef MULTIPROCESSOR - movq CPUVAR(GDT),%rax -#else - movq _C_LABEL(gdtstore)(%rip),%rax -#endif - - /* Switch address space. */ - movq PCB_CR3(%r8),%rcx - movq %rcx,%cr3 - - /* Switch TSS. */ - andl $~0x0200,4-SEL_KPL(%rax,%rdx,1) - ltr %dx - - /* We're always in the kernel, so we don't need the LDT. */ - - /* Restore cr0 (including FPU state). */ - movl PCB_CR0(%r8),%ecx - movq %rcx,%cr0 - - /* Record new pcb. */ - SET_CURPCB(%r8) - - /* Interrupts are okay again. */ - sti +ENTRY(cpu_idle_enter) + ret - /* - * Schedule the dead process's vmspace and stack to be freed. - * {lpw_}exit2(l). Function still in %rsi (2nd arg), proc in - * %rdi (first arg). - */ +ENTRY(cpu_idle_cycle) + hlt + ret - call *%rsi +ENTRY(cpu_idle_leave) + ret - /* Jump into cpu_switch() with the right state. */ - xorq %r13,%r13 - movq %r13, CPUVAR(CURPROC) - jmp switch_search /* * savectx(struct pcb *pcb); diff --git a/sys/arch/amd64/amd64/mptramp.S b/sys/arch/amd64/amd64/mptramp.S index 397c672f36c..20346084081 100644 --- a/sys/arch/amd64/amd64/mptramp.S +++ b/sys/arch/amd64/amd64/mptramp.S @@ -1,4 +1,4 @@ -/* $OpenBSD: mptramp.S,v 1.3 2005/07/26 08:38:29 art Exp $ */ +/* $OpenBSD: mptramp.S,v 1.4 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: mptramp.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */ /*- @@ -235,5 +235,4 @@ _C_LABEL(cpu_spinup_trampoline_end): #end of code copied to MP_TRAMPOLINE movl PCB_CR0(%rsi),%eax movq %rax,%cr0 call _C_LABEL(cpu_hatch) - xorq %r13,%r13 - jmp _C_LABEL(mpidle) + /* NOTREACHED */ diff --git a/sys/arch/amd64/amd64/vm_machdep.c b/sys/arch/amd64/amd64/vm_machdep.c index 7cb5179c909..1b6fa8463b8 100644 --- a/sys/arch/amd64/amd64/vm_machdep.c +++ b/sys/arch/amd64/amd64/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.10 2007/05/27 20:59:25 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.11 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */ /*- @@ -169,12 +169,8 @@ cpu_exit(struct proc *p) if (p->p_md.md_flags & MDP_USEDMTRR) mtrr_clean(p); - /* - * No need to do user LDT cleanup here; it's handled in - * pmap_destroy(). - */ - - switch_exit(p, exit2); + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64 index 3c5fa842f78..6cd06816c70 100644 --- a/sys/arch/amd64/conf/files.amd64 +++ b/sys/arch/amd64/conf/files.amd64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.amd64,v 1.35 2007/10/07 18:41:07 mbalmer Exp $ +# $OpenBSD: files.amd64,v 1.36 2007/10/10 15:53:51 art Exp $ maxpartitions 16 maxusers 2 16 128 @@ -18,7 +18,6 @@ file arch/amd64/amd64/syscall.c file arch/amd64/amd64/trap.c file arch/amd64/amd64/vm_machdep.c file arch/amd64/amd64/fpu.c -file arch/amd64/amd64/Locore.c file arch/amd64/amd64/softintr.c file arch/amd64/amd64/i8259.c file arch/amd64/amd64/cacheinfo.c diff --git a/sys/arch/arm/arm/cpuswitch.S b/sys/arch/arm/arm/cpuswitch.S index d94219d88c0..544f7c27243 100644 --- a/sys/arch/arm/arm/cpuswitch.S +++ b/sys/arch/arm/arm/cpuswitch.S @@ -1,4 +1,4 @@ -/* $OpenBSD: cpuswitch.S,v 1.7 2007/05/14 07:07:09 art Exp $ */ +/* $OpenBSD: cpuswitch.S,v 1.8 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $ */ /* @@ -123,142 +123,11 @@ .text -.Lwhichqs: - .word _C_LABEL(whichqs) - -.Lqs: - .word _C_LABEL(qs) - -/* - * On entry - * r0 = process - */ - -ENTRY(setrunqueue) - /* - * Local register usage - * r0 = process - * r1 = queue - * r2 = &qs[queue] and temp - * r3 = temp - * r12 = whichqs - */ -#ifdef DIAGNOSTIC - ldr r1, [r0, #(P_BACK)] - teq r1, #0x00000000 - bne Lsetrunqueue_erg - - ldr r1, [r0, #(P_WCHAN)] - teq r1, #0x00000000 - bne Lsetrunqueue_erg -#endif - - /* Get the priority of the queue */ - ldrb r1, [r0, #(P_PRIORITY)] - mov r1, r1, lsr #2 - - /* Indicate that there is a process on this queue */ - ldr r12, .Lwhichqs - ldr r2, [r12] - mov r3, #0x00000001 - mov r3, r3, lsl r1 - orr r2, r2, r3 - str r2, [r12] - - /* Get the address of the queue */ - ldr r2, .Lqs - add r1, r2, r1, lsl # 3 - - /* Hook the process in */ - str r1, [r0, #(P_FORW)] - ldr r2, [r1, #(P_BACK)] - - str r0, [r1, #(P_BACK)] -#ifdef DIAGNOSTIC - teq r2, #0x00000000 - beq Lsetrunqueue_erg -#endif - str r0, [r2, #(P_FORW)] - str r2, [r0, #(P_BACK)] - - mov pc, lr - -#ifdef DIAGNOSTIC -Lsetrunqueue_erg: - mov r2, r1 - mov r1, r0 - add r0, pc, #Ltext1 - . - 8 - bl _C_LABEL(printf) - - ldr r2, .Lqs - ldr r1, [r2] - add r0, pc, #Ltext2 - . - 8 - b _C_LABEL(panic) - -Ltext1: - .asciz "setrunqueue : %08x %08x\n" -Ltext2: - .asciz "setrunqueue : [qs]=%08x qs=%08x\n" - .align 0 -#endif - -/* - * On entry - * r0 = process - */ - -ENTRY(remrunqueue) - /* - * Local register usage - * r0 = oldproc - * r1 = queue - * r2 = &qs[queue] and scratch - * r3 = scratch - * r12 = whichqs - */ - - /* Get the priority of the queue */ - ldrb r1, [r0, #(P_PRIORITY)] - mov r1, r1, lsr #2 - - /* Unhook the process */ - ldr r2, [r0, #(P_FORW)] - ldr r3, [r0, #(P_BACK)] - - str r3, [r2, #(P_BACK)] - str r2, [r3, #(P_FORW)] - - /* If the queue is now empty clear the queue not empty flag */ - teq r2, r3 - - /* This could be reworked to avoid the use of r4 */ - ldreq r12, .Lwhichqs - ldreq r2, [r12] - moveq r3, #0x00000001 - moveq r3, r3, lsl r1 - biceq r2, r2, r3 - streq r2, [r12] - - /* Remove the back pointer for the process */ - mov r1, #0x00000000 - str r1, [r0, #(P_BACK)] - - mov pc, lr - - -/* - * cpuswitch() - * - * preforms a process context switch. - * This function has several entry points - */ - .Lcpu_info_store: .word _C_LABEL(cpu_info_store) .Lcurproc: .word _C_LABEL(cpu_info_store) + CI_CURPROC - .Lwant_resched: .word _C_LABEL(want_resched) @@ -289,320 +158,123 @@ _C_LABEL(curpcb): /* * Idle loop, exercised while waiting for a process to wake up. - * - * NOTE: When we jump back to .Lswitch_search, we must have a - * pointer to whichqs in r7, which is what it is when we arrive - * here. */ -/* LINTSTUB: Ignore */ -ASENTRY_NP(idle) - ldr r6, .Lcpu_do_powersave - IRQenable /* Enable interrupts */ - ldr r6, [r6] /* r6 = cpu_do_powersave */ +ENTRY(cpu_idle_enter) + stmfd sp!, {lr} -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bl _C_LABEL(sched_unlock_idle) -#endif + IRQenable /* Enable interrupts */ /* Drop to spl0 (returns the current spl level in r0). */ mov r0, #(IPL_NONE) bl _C_LABEL(_spllower) + ldmfd sp!, {pc} + +ENTRY(cpu_idle_cycle) + stmfd sp!, {r6, lr} + + ldr r6, .Lcpu_do_powersave + ldr r6, [r6] /* r6 = cpu_do_powersave */ + teq r6, #0 /* cpu_do_powersave non zero? */ ldrne r6, .Lcpufuncs - mov r4, r0 /* Old interrupt level to r4 */ ldrne r6, [r6, #(CF_SLEEP)] - /* - * Main idle loop. - * r6 points to power-save idle function if required, else NULL. - */ -1: ldr r3, [r7] /* r3 = sched_whichqs */ - teq r3, #0 - bne 2f /* We have work to do */ teq r6, #0 /* Powersave idle? */ - beq 1b /* Nope. Just sit-n-spin. */ + beq 1f /* Nope. Just continue. */ /* - * Before going into powersave idle mode, disable interrupts - * and check sched_whichqs one more time. + * Before going into powersave idle mode, disable interrupts. */ IRQdisableALL - ldr r3, [r7] - mov r0, #0 - teq r3, #0 /* sched_whichqs still zero? */ - moveq lr, pc - moveq pc, r6 /* If so, do powersave idle */ + mov lr, pc + mov pc, r6 /* If so, do powersave idle */ IRQenableALL - b 1b /* Back around */ - /* - * sched_whichqs indicates that at least one proc is ready to run. - * Restore the original interrupt priority level, grab the - * scheduler lock if necessary, and jump back into cpu_switch. - */ -2: mov r0, r4 -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bl _C_LABEL(splx) - adr lr, .Lswitch_search - b _C_LABEL(sched_lock_idle) -#else - adr lr, .Lswitch_search - b _C_LABEL(splx) -#endif +1: ldmfd sp!, {r6, pc} + +ENTRY(cpu_idle_leave) + stmfd sp!, {lr} + + mov r0, #(IPL_SCHED) + bl _C_LABEL(_splraise) + + ldmfd sp!, {pc} /* - * Find a new lwp to run, save the current context and - * load the new context + * cpu_switchto(struct proc *oldproc, struct proc *newproc) + * + * Performs a process context switch from oldproc (which may be NULL) + * to newproc. * * Arguments: - * r0 'struct proc *' of the current LWP + * r0 'struct proc *' of the context to switch from + * r1 'struct proc *' of the context to switch to */ -ENTRY(cpu_switch) -/* - * Local register usage. Some of these registers are out of date. - * r1 = oldproc - * r2 = spl level - * r3 = whichqs - * r4 = queue - * r5 = &qs[queue] - * r6 = newlwp - * r7 = scratch - */ +ENTRY(cpu_switchto) stmfd sp!, {r4-r7, lr} - /* - * Indicate that there is no longer a valid process (curlwp = 0). - * Zero the current PCB pointer while we're at it. - */ - ldr r7, .Lcurproc - ldr r6, .Lcurpcb - mov r2, #0x00000000 - str r2, [r7] /* curproc = NULL */ - str r2, [r6] /* curpcb = NULL */ - - /* stash the old proc while we call functions */ - mov r5, r0 - - /* First phase : find a new proc */ - ldr r7, .Lwhichqs - - /* rem: r5 = old proc */ - /* rem: r7 = &whichqs */ - -.Lswitch_search: - IRQdisable - - /* Do we have any active queues */ - ldr r3, [r7] - - /* If not we must idle until we do. */ - teq r3, #0x00000000 - beq _ASM_LABEL(idle) - - /* put old proc back in r1 */ - mov r1, r5 - - /* rem: r1 = old proc */ - /* rem: r3 = whichqs */ - /* rem: interrupts are disabled */ - - /* used further down, saves SA stall */ - ldr r6, .Lqs - - /* - * We have found an active queue. Currently we do not know which queue - * is active just that one of them is. - */ - /* Non-Xscale version of the ffs algorithm devised by d.seal and - * posted to comp.sys.arm on 16 Feb 1994. - */ - rsb r5, r3, #0 - ands r0, r3, r5 - -#ifndef __XSCALE__ - adr r5, .Lcpu_switch_ffs_table - - /* X = R0 */ - orr r4, r0, r0, lsl #4 /* r4 = X * 0x11 */ - orr r4, r4, r4, lsl #6 /* r4 = X * 0x451 */ - rsb r4, r4, r4, lsl #16 /* r4 = X * 0x0450fbaf */ - - /* now lookup in table indexed on top 6 bits of a4 */ - ldrb r4, [ r5, r4, lsr #26 ] - -#else /* __XSCALE__ */ - clz r4, r0 - rsb r4, r4, #31 -#endif /* __XSCALE__ */ - - /* rem: r0 = bit mask of chosen queue (1 << r4) */ - /* rem: r1 = old proc */ - /* rem: r3 = whichqs */ - /* rem: r4 = queue number */ - /* rem: interrupts are disabled */ - - /* Get the address of the queue (&qs[queue]) */ - add r5, r6, r4, lsl #3 - - /* - * Get the proc from the queue and place the next process in - * the queue at the head. This basically unlinks the lwp at - * the head of the queue. - */ - ldr r6, [r5, #(P_FORW)] - -#ifdef DIAGNOSTIC - cmp r6, r5 - beq .Lswitch_bogons -#endif - - /* rem: r6 = new proc */ - ldr r7, [r6, #(P_FORW)] - str r7, [r5, #(P_FORW)] - - /* - * Test to see if the queue is now empty. If the head of the queue - * points to the queue itself then there are no more procs in - * the queue. We can therefore clear the queue not empty flag held - * in r3. - */ - - teq r5, r7 - biceq r3, r3, r0 - - /* rem: r0 = bit mask of chosen queue (1 << r4) - NOT NEEDED AN MORE */ - - /* Fix the back pointer for the lwp now at the head of the queue. */ - ldr r0, [r6, #(P_BACK)] - str r0, [r7, #(P_BACK)] - - /* Update the RAM copy of the queue not empty flags word. */ - ldreq r7, .Lwhichqs - streq r3, [r7] - - /* rem: r1 = old proc */ - /* rem: r3 = whichqs - NOT NEEDED ANY MORE */ - /* rem: r4 = queue number - NOT NEEDED ANY MORE */ - /* rem: r6 = new proc */ - /* rem: interrupts are disabled */ - /* Clear the want_resched flag */ ldr r7, .Lwant_resched - mov r0, #0x00000000 - str r0, [r7] - - /* - * Clear the back pointer of the proc we have removed from - * the head of the queue. The new proc is isolated now. - */ - str r0, [r6, #(P_BACK)] - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - /* - * unlock the sched_lock, but leave interrupts off, for now. - */ - mov r7, r1 - bl _C_LABEL(sched_unlock_idle) - mov r1, r7 -#endif - - -.Lswitch_resume: - /* rem: r1 = old proc */ - /* rem: r4 = return value [not used if came from cpu_switchto()] */ - /* rem: r6 = new process */ - /* rem: interrupts are disabled */ + mov r2, #0x00000000 + str r2, [r7] #ifdef MULTIPROCESSOR /* XXX use curcpu() */ - ldr r0, .Lcpu_info_store - str r0, [r6, #(P_CPU)] + ldr r2, .Lcpu_info_store + str r2, [r1, #(P_CPU)] #else - /* l->l_cpu initialized in fork1() for single-processor */ + /* p->p_cpu initialized in fork1() for single-processor */ #endif /* Process is now on a processor. */ - mov r0, #SONPROC /* p->p_stat = SONPROC */ - strb r0, [r6, #(P_STAT)] + mov r2, #SONPROC /* p->p_stat = SONPROC */ + strb r2, [r1, #(P_STAT)] /* We have a new curproc now so make a note it */ ldr r7, .Lcurproc - str r6, [r7] + str r1, [r7] /* Hook in a new pcb */ ldr r7, .Lcurpcb - ldr r0, [r6, #(P_ADDR)] - str r0, [r7] - - /* At this point we can allow IRQ's again. */ - IRQenable - - /* rem: r1 = old proc */ - /* rem: r4 = return value */ - /* rem: r6 = new process */ - /* rem: interrupts are enabled */ - - /* - * If the new process is the same as the process that called - * cpu_switch() then we do not need to save and restore any - * contexts. This means we can make a quick exit. - * The test is simple if curproc on entry (now in r1) is the - * same as the proc removed from the queue we can jump to the exit. - */ - teq r1, r6 - moveq r4, #0x00000000 /* default to "didn't switch" */ - beq .Lswitch_return - - /* - * At this point, we are guaranteed to be switching to - * a new proc. - */ - mov r4, #0x00000001 - - /* Remember the old proc in r0 */ - mov r0, r1 + ldr r6, [r7] /* Remember the old PCB */ + ldr r2, [r1, #(P_ADDR)] + str r2, [r7] /* * If the old proc on entry to cpu_switch was zero then the * process that called it was exiting. This means that we do - * not need to save the current context. Instead we can jump - * straight to restoring the context for the new process. + * not need to save the current context (we nevertheless need + * to clear the cache and TLB). */ teq r0, #0x00000000 beq .Lswitch_exited - /* rem: r0 = old proc */ - /* rem: r4 = return value */ - /* rem: r6 = new process */ - /* rem: interrupts are enabled */ - /* Stage two : Save old context */ - /* Get the user structure for the old proc. */ - ldr r1, [r0, #(P_ADDR)] - /* Save all the registers in the old proc's pcb */ #ifndef __XSCALE__ - add r7, r1, #(PCB_R8) + add r7, r6, #(PCB_R8) stmia r7, {r8-r13} #else - strd r8, [r1, #(PCB_R8)] - strd r10, [r1, #(PCB_R10)] - strd r12, [r1, #(PCB_R12)] + strd r8, [r6, #(PCB_R8)] + strd r10, [r6, #(PCB_R10)] + strd r12, [r6, #(PCB_R12)] #endif +.Lswitch_exited: /* * NOTE: We can now use r8-r13 until it is time to restore * them for the new process. */ /* Remember the old PCB. */ - mov r8, r1 + mov r8, r6 - /* r1 now free! */ + /* Save new proc in r6 now. */ + mov r6, r1 /* Get the user structure for the new process in r9 */ ldr r9, [r6, #(P_ADDR)] @@ -616,28 +288,24 @@ ENTRY(cpu_switch) orr r2, r2, #(PSR_UND32_MODE | I32_bit) msr cpsr_c, r2 +#ifdef notworthit + teq r0, #0x00000000 + strne sp, [r8, #(PCB_UND_SP)] +#else str sp, [r8, #(PCB_UND_SP)] +#endif msr cpsr_c, r3 /* Restore the old mode */ /* rem: r0 = old proc */ - /* rem: r4 = return value */ - /* rem: r6 = new process */ + /* rem: r1 = r6 = new process */ /* rem: r8 = old PCB */ /* rem: r9 = new PCB */ - /* rem: interrupts are enabled */ /* What else needs to be saved Only FPA stuff when that is supported */ /* Third phase : restore saved context */ - /* rem: r0 = old proc */ - /* rem: r4 = return value */ - /* rem: r6 = new proc */ - /* rem: r8 = old PCB */ - /* rem: r9 = new PCB */ - /* rem: interrupts are enabled */ - /* * Get the new L1 table pointer into r11. If we're switching to * an LWP with the same address space as the outgoing one, we can @@ -652,7 +320,7 @@ ENTRY(cpu_switch) ldr r0, [r8, #(PCB_DACR)] /* r0 = old DACR */ ldr r1, [r9, #(PCB_DACR)] /* r1 = new DACR */ ldr r8, [r9, #(PCB_CSTATE)] /* r8 = &new_pmap->pm_cstate */ - ldr r5, .Llast_cache_state_ptr /* Previous thread's cstate */ + ldr r5, .Llast_cache_state_ptr /* Previous proc's cstate */ teq r10, r11 /* Same L1? */ ldr r5, [r5] @@ -681,7 +349,7 @@ ENTRY(cpu_switch) beq .Lcs_cache_purge_skipped /* VM space is not in cache */ /* - * Definately need to flush the cache. + * Definitely need to flush the cache. * Mark the old VM space as NOT being resident in the cache. */ mov r2, #0x00000000 @@ -696,7 +364,6 @@ ENTRY(cpu_switch) .Lcs_cache_purge_skipped: /* rem: r1 = new DACR */ - /* rem: r4 = return value */ /* rem: r5 = &old_pmap->pm_cstate (or NULL) */ /* rem: r6 = new proc */ /* rem: r8 = &new_pmap->pm_cstate */ @@ -787,7 +454,6 @@ ENTRY(cpu_switch) cmp r5, r8 strne r8, [r0] - /* rem: r4 = return value */ /* rem: r6 = new proc */ /* rem: r9 = new PCB */ @@ -820,14 +486,6 @@ ENTRY(cpu_switch) ldr r13, [r7, #(PCB_SP)] #endif -#if 0 - ldr r5, [r6, #(L_PROC)] /* fetch the proc for below */ -#else - mov r5, r6 -#endif - - /* rem: r4 = return value */ - /* rem: r5 = new proc's proc */ /* rem: r6 = new proc */ /* rem: r7 = new pcb */ @@ -840,234 +498,16 @@ ENTRY(cpu_switch) /* We can enable interrupts again */ IRQenableALL - /* rem: r4 = return value */ - /* rem: r5 = new proc's proc */ /* rem: r6 = new proc */ /* rem: r7 = new PCB */ -#if 0 - /* - * Check for restartable atomic sequences (RAS). - */ - - ldr r2, [r5, #(P_RASLIST)] - ldr r1, [r7, #(PCB_TF)] /* r1 = trapframe (used below) */ - teq r2, #0 /* p->p_nras == 0? */ - bne .Lswitch_do_ras /* no, check for one */ -#endif - .Lswitch_return: - /* cpu_switch returns 1 == switched, 0 == didn't switch */ - mov r0, r4 - /* * Pull the registers that got pushed when either savectx() or * cpu_switch() was called and return. */ ldmfd sp!, {r4-r7, pc} -#if 0 -.Lswitch_do_ras: - ldr r1, [r1, #(TF_PC)] /* second ras_lookup() arg */ - mov r0, r5 /* first ras_lookup() arg */ - bl _C_LABEL(ras_lookup) - cmn r0, #1 /* -1 means "not in a RAS" */ - ldrne r1, [r7, #(PCB_TF)] - strne r0, [r1, #(TF_PC)] - b .Lswitch_return -#endif - -.Lswitch_exited: - /* - * We skip the cache purge because switch_exit() already did it. - * Load up registers the way .Lcs_cache_purge_skipped expects. - * Userpsace access already blocked by switch_exit(). - */ - ldr r9, [r6, #(P_ADDR)] /* r9 = new PCB */ - mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */ - mov r5, #0 /* No previous cache state */ - ldr r1, [r9, #(PCB_DACR)] /* r1 = new DACR */ - ldr r8, [r9, #(PCB_CSTATE)] /* r8 = new cache state */ - ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */ - b .Lcs_cache_purge_skipped - - -#ifdef DIAGNOSTIC -.Lswitch_bogons: - adr r0, .Lswitch_panic_str - bl _C_LABEL(panic) -1: nop - b 1b - -.Lswitch_panic_str: - .asciz "cpu_switch: sched_qs empty with non-zero sched_whichqs!\n" -#endif - -/* - * cpu_switchto(struct proc *current, struct proc *next) - * Switch to the specified next LWP - * Arguments: - * - * r0 'struct proc *' of the current LWP - * r1 'struct proc *' of the LWP to switch to - */ -ENTRY(cpu_switchto) - stmfd sp!, {r4-r7, lr} - - mov r6, r1 /* save new proc */ - -#if defined(LOCKDEBUG) - mov r5, r0 /* save old proc */ - bl _C_LABEL(sched_unlock_idle) - mov r1, r5 -#else - mov r1, r0 -#endif - - IRQdisable - - /* - * Okay, set up registers the way cpu_switch() wants them, - * and jump into the middle of it (where we bring up the - * new process). - * - * r1 = old proc (r6 = new proc) - */ - b .Lswitch_resume - -/* - * void switch_exit(struct proc *l, struct proc *l0, - * void (*exit)(struct proc *)); - * Switch to proc0's saved context and deallocate the address space and kernel - * stack for l. Then jump into cpu_switch(), as if we were in proc0 all along. - */ - -/* LINTSTUB: Func: void switch_exit(struct proc *l, struct proc *l0, - void (*func)(struct proc *)) */ -ENTRY(switch_exit) - /* - * The process is going away, so we can use callee-saved - * registers here without having to save them. - */ - - mov r4, r0 - ldr r0, .Lcurproc - - mov r5, r1 - mov r6, r2 - - /* - * r4 = proc - * r5 = proc0 - * r6 = exit func - */ - - mov r2, #0x00000000 /* curproc = NULL */ - str r2, [r0] - - /* - * We're about to clear both the cache and the TLB. - * Make sure to zap the 'last cache state' pointer since the - * pmap might be about to go away. Also ensure the outgoing - * VM space's cache state is marked as NOT resident in the - * cache, and that proc0's cache state IS resident. - */ - ldr r7, [r4, #(P_ADDR)] /* r7 = old proc's PCB */ - ldr r0, .Llast_cache_state_ptr /* Last userland cache state */ - ldr r9, [r7, #(PCB_CSTATE)] /* Fetch cache state pointer */ - ldr r3, [r5, #(P_ADDR)] /* r3 = proc0's PCB */ - str r2, [r0] /* No previous cache state */ - str r2, [r9, #(CS_ALL)] /* Zap old proc's cache state */ - ldr r3, [r3, #(PCB_CSTATE)] /* proc0's cache state */ - mov r2, #-1 - str r2, [r3, #(CS_ALL)] /* proc0 is in da cache! */ - - /* Switch to proc0 context */ - - ldr r9, .Lcpufuncs - mov lr, pc - ldr pc, [r9, #CF_IDCACHE_WBINV_ALL] - - ldr r0, [r7, #(PCB_PL1VEC)] - ldr r1, [r7, #(PCB_DACR)] - - /* - * r0 = Pointer to L1 slot for vector_page (or NULL) - * r1 = proc0's DACR - * r4 = proc we're switching from - * r5 = proc0 - * r6 = exit func - * r7 = proc0's PCB - * r9 = cpufuncs - */ - - IRQdisableALL - - /* - * Ensure the vector table is accessible by fixing up proc0's L1 - */ - cmp r0, #0 /* No need to fixup vector table? */ - ldrne r3, [r0] /* But if yes, fetch current value */ - ldrne r2, [r7, #(PCB_L1VEC)] /* Fetch new vector_page value */ - mcr p15, 0, r1, c3, c0, 0 /* Update DACR for proc0's context */ - cmpne r3, r2 /* Stuffing the same value? */ - strne r2, [r0] /* Store if not. */ - -#ifdef PMAP_INCLUDE_PTE_SYNC - /* - * Need to sync the cache to make sure that last store is - * visible to the MMU. - */ - movne r1, #4 - movne lr, pc - ldrne pc, [r9, #CF_DCACHE_WB_RANGE] -#endif /* PMAP_INCLUDE_PTE_SYNC */ - - /* - * Note: We don't do the same optimisation as cpu_switch() with - * respect to avoiding flushing the TLB if we're switching to - * the same L1 since this process' VM space may be about to go - * away, so we don't want *any* turds left in the TLB. - */ - - /* Switch the memory to the new process */ - ldr r0, [r7, #(PCB_PAGEDIR)] - mov lr, pc - ldr pc, [r9, #CF_CONTEXT_SWITCH] - - ldr r0, .Lcurpcb - - /* Restore all the save registers */ -#ifndef __XSCALE__ - add r1, r7, #PCB_R8 - ldmia r1, {r8-r13} -#else - ldr r8, [r7, #(PCB_R8)] - ldr r9, [r7, #(PCB_R9)] - ldr r10, [r7, #(PCB_R10)] - ldr r11, [r7, #(PCB_R11)] - ldr r12, [r7, #(PCB_R12)] - ldr r13, [r7, #(PCB_SP)] -#endif - str r7, [r0] /* curpcb = proc0's PCB */ - - IRQenableALL - - /* - * Schedule the vmspace and stack to be freed. - */ - mov r0, r4 /* {proc_}exit2(l) */ - mov lr, pc - mov pc, r6 - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bl _C_LABEL(sched_lock_idle) -#endif - - ldr r7, .Lwhichqs /* r7 = &whichqs */ - mov r5, #0x00000000 /* r5 = old proc = NULL */ - b .Lswitch_search - /* LINTSTUB: Func: void savectx(struct pcb *pcb) */ ENTRY(savectx) /* @@ -1110,18 +550,3 @@ ENTRY(proc_trampoline) PULLFRAME movs pc, lr /* Exit */ - -#ifndef __XSCALE__ - .type .Lcpu_switch_ffs_table, _ASM_TYPE_OBJECT; -.Lcpu_switch_ffs_table: -/* same as ffs table but all nums are -1 from that */ -/* 0 1 2 3 4 5 6 7 */ - .byte 0, 0, 1, 12, 2, 6, 0, 13 /* 0- 7 */ - .byte 3, 0, 7, 0, 0, 0, 0, 14 /* 8-15 */ - .byte 10, 4, 0, 0, 8, 0, 0, 25 /* 16-23 */ - .byte 0, 0, 0, 0, 0, 21, 27, 15 /* 24-31 */ - .byte 31, 11, 5, 0, 0, 0, 0, 0 /* 32-39 */ - .byte 9, 0, 0, 24, 0, 0, 20, 26 /* 40-47 */ - .byte 30, 0, 0, 0, 0, 23, 0, 19 /* 48-55 */ - .byte 29, 0, 22, 18, 28, 17, 16, 0 /* 56-63 */ -#endif /* !__XSCALE_ */ diff --git a/sys/arch/arm/arm/genassym.cf b/sys/arch/arm/arm/genassym.cf index 63839e12196..3ffdb707531 100644 --- a/sys/arch/arm/arm/genassym.cf +++ b/sys/arch/arm/arm/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.7 2007/05/14 07:07:09 art Exp $ +# $OpenBSD: genassym.cf,v 1.8 2007/10/10 15:53:51 art Exp $ # $NetBSD: genassym.cf,v 1.27 2003/11/04 10:33:16 dsl Exp$ # Copyright (c) 1982, 1990 The Regents of the University of California. @@ -82,11 +82,9 @@ export P_PROFIL export SONPROC struct proc -member p_forw -member p_back member p_addr -member p_priority -member p_wchan +#member p_priority +#member p_wchan member p_stat # XXX use PROC_SIZEOF in new code whenever possible define PROCSIZE sizeof(struct proc) diff --git a/sys/arch/arm/arm/pmap.c b/sys/arch/arm/arm/pmap.c index b19bce07a63..d9c0035b3a8 100644 --- a/sys/arch/arm/arm/pmap.c +++ b/sys/arch/arm/arm/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.13 2007/05/18 14:41:55 art Exp $ */ +/* $OpenBSD: pmap.c,v 1.14 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: pmap.c,v 1.147 2004/01/18 13:03:50 scw Exp $ */ /* @@ -3100,11 +3100,6 @@ pmap_activate(struct proc *p) } void -pmap_deactivate(struct proc *p) -{ -} - -void pmap_update(pmap_t pm) { @@ -3211,7 +3206,7 @@ pmap_destroy(pmap_t pm) pmap_update(pm); /* - * Make sure cpu_switch(), et al, DTRT. This is safe to do + * Make sure cpu_switchto(), et al, DTRT. This is safe to do * since this process has no remaining mappings of its own. */ curpcb->pcb_pl1vec = pcb->pcb_pl1vec; diff --git a/sys/arch/arm/arm/vm_machdep.c b/sys/arch/arm/arm/vm_machdep.c index d5e109dc121..a3b4115793b 100644 --- a/sys/arch/arm/arm/vm_machdep.c +++ b/sys/arch/arm/arm/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.6 2007/05/27 20:59:25 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.7 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.31 2004/01/04 11:33:29 jdolecek Exp $ */ /* @@ -73,8 +73,6 @@ extern pv_addr_t systempage; int process_read_regs (struct proc *p, struct reg *regs); int process_read_fpregs (struct proc *p, struct fpreg *regs); -void switch_exit (struct proc *p, struct proc *p0, - void (*)(struct proc *)); extern void proc_trampoline (void); /* @@ -85,23 +83,6 @@ extern void proc_trampoline (void); * the amount of stack used. */ -#if 0 -void -cpu_proc_fork(p1, p2) - struct proc *p1, *p2; -{ - -#if defined(PERFCTRS) - if (PMC_ENABLED(p1)) - pmc_md_fork(p1, p2); - else { - p2->p_md.pmc_enabled = 0; - p2->p_md.pmc_state = NULL; - } -#endif -} -#endif - /* * Finish a fork operation, with process p2 nearly set up. * Copy and update the pcb and trap frame, making the child ready to run. @@ -201,27 +182,14 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) pcb->pcb_un.un_32.pcb32_sp = (u_int)sf; } -#if 0 -void -cpu_setfunc(struct proc *p, void (*func)(void *), void *arg) -{ - struct pcb *pcb = &p->p_addr->u_pcb; - struct trapframe *tf = pcb->pcb_tf; - struct switchframe *sf = (struct switchframe *)tf - 1; - - sf->sf_r4 = (u_int)func; - sf->sf_r5 = (u_int)arg; - sf->sf_pc = (u_int)proc_trampoline; - pcb->pcb_un.un_32.pcb32_sp = (u_int)sf; -} -#endif - - void cpu_exit(struct proc *p) { +#if 0 pmap_update(p->p_vmspace->vm_map.pmap); /* XXX DSR help stability */ - switch_exit(p, &proc0, exit2); +#endif + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/arm/include/pmap.h b/sys/arch/arm/include/pmap.h index 847374df0ae..2e5b139324d 100644 --- a/sys/arch/arm/include/pmap.h +++ b/sys/arch/arm/include/pmap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.h,v 1.8 2007/09/10 18:49:44 miod Exp $ */ +/* $OpenBSD: pmap.h,v 1.9 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: pmap.h,v 1.76 2003/09/06 09:10:46 rearnsha Exp $ */ /* @@ -241,12 +241,13 @@ extern int pmap_debug_level; /* Only exists if PMAP_DEBUG */ #define pmap_is_referenced(pg) \ (((pg)->mdpage.pvh_attrs & PVF_REF) != 0) -#define pmap_copy(dp, sp, da, l, sa) /* nothing */ +#define pmap_deactivate(p) do { /* nothing */ } while (0) +#define pmap_copy(dp, sp, da, l, sa) do { /* nothing */ } while (0) #define pmap_phys_address(ppn) (ptoa(ppn)) -#define pmap_proc_iflush(p, va, len) /* nothing */ -#define pmap_unuse_final(p) /* nothing */ +#define pmap_proc_iflush(p, va, len) do { /* nothing */ } while (0) +#define pmap_unuse_final(p) do { /* nothing */ } while (0) #define pmap_remove_holes(map) do { /* nothing */ } while (0) /* diff --git a/sys/arch/aviion/aviion/locore.S b/sys/arch/aviion/aviion/locore.S index 3b9ef76b003..dae5f31e0c4 100644 --- a/sys/arch/aviion/aviion/locore.S +++ b/sys/arch/aviion/aviion/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.3 2006/05/20 22:40:43 miod Exp $ */ +/* $OpenBSD: locore.S,v 1.4 2007/10/10 15:53:51 art Exp $ */ /* * Copyright (c) 2005, Miodrag Vallat. * Copyright (c) 1998 Steve Murphree, Jr. @@ -343,14 +343,6 @@ GLOBAL(secondary_start) bsr.n _C_LABEL(secondary_main) addu r31, r3, USIZE /* switch to idle stack */ - /* - * At this point, the CPU has been correctly initialized and has - * identified itself on the console. - * All it needs now is to jump to the idle loop and wait for work to - * be offered. - */ - br _ASM_LABEL(cpu_switch_idle) - #endif /* MULTIPROCESSOR */ /* diff --git a/sys/arch/aviion/aviion/machdep.c b/sys/arch/aviion/aviion/machdep.c index 4676e19f088..8464a564ee1 100644 --- a/sys/arch/aviion/aviion/machdep.c +++ b/sys/arch/aviion/aviion/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.10 2007/06/06 17:15:11 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.11 2007/10/10 15:53:51 art Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -225,8 +225,6 @@ cpu_startup() { caddr_t v; int sz, i; - vsize_t size; - int base, residual; vaddr_t minaddr, maxaddr; /* @@ -605,19 +603,18 @@ void secondary_main() { struct cpu_info *ci = curcpu(); + int s; cpu_configuration_print(0); + sched_init_cpu(ci); ncpus++; __cpu_simple_unlock(&cpu_mutex); microuptime(&ci->ci_schedstate.spc_runtime); ci->ci_curproc = NULL; - /* - * Upon return, the secondary cpu bootstrap code in locore will - * enter the idle loop, waiting for some food to process on this - * processor. - */ + SCHED_LOCK(s); + cpu_switchto(NULL, sched_chooseproc()); } #endif /* MULTIPROCESSOR */ diff --git a/sys/arch/hp300/hp300/locore.s b/sys/arch/hp300/hp300/locore.s index 40a595f59c0..fe200e1a6fe 100644 --- a/sys/arch/hp300/hp300/locore.s +++ b/sys/arch/hp300/hp300/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.60 2007/05/15 13:46:22 martin Exp $ */ +/* $OpenBSD: locore.s,v 1.61 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: locore.s,v 1.91 1998/11/11 06:41:25 thorpej Exp $ */ /* @@ -1345,51 +1345,18 @@ Ldorte: */ #include <m68k/m68k/support.s> -/* - * Use common m68k process manipulation routines. - */ -#include <m68k/m68k/proc_subr.s> - .data GLOBAL(curpcb) .long 0 ASBSS(nullpcb,SIZEOF_PCB) -/* - * At exit of a process, do a switch for the last time. - * Switch to a safe stack and PCB, and deallocate the process's resources. - */ -ENTRY(switch_exit) - movl sp@(4),a0 - /* save state into garbage pcb */ - movl #_ASM_LABEL(nullpcb),_C_LABEL(curpcb) - lea _ASM_LABEL(tmpstk),sp | goto a tmp stack - - /* Schedule the vmspace and stack to be freed. */ - movl a0,sp@- | exit2(p) - jbsr _C_LABEL(exit2) - lea sp@(4),sp | pop args - - jra _C_LABEL(cpu_switch) - -/* - * When no processes are on the runq, Swtch branches to Idle - * to wait for something to come ready. - */ -ASENTRY_NOPROFILE(Idle) +ENTRY_NOPROFILE(cpu_idle_cycle) stop #PSL_LOWIPL - movw #PSL_HIGHIPL,sr - movl _C_LABEL(whichqs),d0 - jeq _ASM_LABEL(Idle) - jra Lsw1 - -Lbadsw: - PANIC("switch") - /*NOTREACHED*/ + rts /* - * cpu_switch() + * cpu_switchto(struct proc *oldproc, struct proc *newproc) * * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the * entire ATC. The effort involved in selective flushing may not be @@ -1399,55 +1366,15 @@ Lbadsw: * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag * bit). For now, we just always flush the full ATC. */ -ENTRY(cpu_switch) - movl _C_LABEL(curpcb),a0 | current pcb - movw sr,a0@(PCB_PS) | save sr before changing ipl -#ifdef notyet - movl CURPROC,sp@- | remember last proc running -#endif - clrl CURPROC +ENTRY(cpu_switchto) + movl sp@(4), d0 | oldproc + beq Lswnofpsave | is NULL, don't save anything /* - * Find the highest-priority queue that isn't empty, - * then take the first proc from that queue. - */ - movw #PSL_HIGHIPL,sr | lock out interrupts - movl _C_LABEL(whichqs),d0 - jeq _ASM_LABEL(Idle) -Lsw1: - movl d0,d1 - negl d0 - andl d1,d0 - bfffo d0{#0:#32},d1 - eorib #31,d1 - - movl d1,d0 - lslb #3,d1 | convert queue number to index - addl #_C_LABEL(qs),d1 | locate queue (q) - movl d1,a1 - movl a1@(P_FORW),a0 | p = q->p_forw - cmpal d1,a0 | anyone on queue? - jeq Lbadsw | no, panic - movl a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw - movl a0@(P_FORW),a1 | n = p->p_forw - movl d1,a1@(P_BACK) | n->p_back = q - cmpal d1,a1 | anyone left on queue? - jne Lsw2 | yes, skip - movl _C_LABEL(whichqs),d1 - bclr d0,d1 | no, clear bit - movl d1,_C_LABEL(whichqs) -Lsw2: - movl a0,CURPROC - clrl _C_LABEL(want_resched) -#ifdef notyet - movl sp@+,a1 - cmpl a0,a1 | switching to same proc? - jeq Lswdone | yes, skip save and restore -#endif - /* * Save state of previous process in its pcb. */ movl _C_LABEL(curpcb),a1 + movw sr, a1@(PCB_PS) | save sr before switching context moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers movl usp,a2 | grab USP (a2 has been saved) movl a2,a1@(PCB_USP) | and save it @@ -1460,16 +1387,12 @@ Lsw2: jeq Lswnofpsave | yes, all done fmovem fp0-fp7,a2@(FPF_REGS) | save FP general registers fmovem fpcr/fpsr/fpi,a2@(FPF_FPCR) | save FP control registers + Lswnofpsave: + movl sp@(8), a0 | newproc -#ifdef DIAGNOSTIC - tstl a0@(P_WCHAN) - jne Lbadsw - cmpb #SRUN,a0@(P_STAT) - jne Lbadsw -#endif + movl a0, CURPROC movb #SONPROC,a0@(P_STAT) - clrl a0@(P_BACK) | clear back link movl a0@(P_ADDR),a1 | get p_addr movl a1,_C_LABEL(curpcb) diff --git a/sys/arch/hp300/hp300/vm_machdep.c b/sys/arch/hp300/hp300/vm_machdep.c index a23b64964ed..abc6af74605 100644 --- a/sys/arch/hp300/hp300/vm_machdep.c +++ b/sys/arch/hp300/hp300/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.43 2007/05/27 20:59:25 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.44 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.60 2001/07/06 05:53:35 chs Exp $ */ /* @@ -133,10 +133,10 @@ void cpu_exit(p) struct proc *p; { + (void)splhigh(); - (void) splhigh(); - switch_exit(p); - /* NOTREACHED */ + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/hppa/hppa/genassym.cf b/sys/arch/hppa/hppa/genassym.cf index 8f4351a2877..dab3e08efc2 100644 --- a/sys/arch/hppa/hppa/genassym.cf +++ b/sys/arch/hppa/hppa/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.30 2007/05/14 19:54:21 martin Exp $ +# $OpenBSD: genassym.cf,v 1.31 2007/10/10 15:53:51 art Exp $ # # Copyright (c) 1982, 1990, 1993 @@ -130,8 +130,6 @@ member tf_cr30 # proc fields and values struct proc -member p_forw -member p_back member p_addr member p_priority member p_stat diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S index a6e0e572e0c..fa875d8a35c 100644 --- a/sys/arch/hppa/hppa/locore.S +++ b/sys/arch/hppa/hppa/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.155 2007/07/20 22:09:23 kettenis Exp $ */ +/* $OpenBSD: locore.S,v 1.156 2007/10/10 15:53:51 art Exp $ */ /* * Copyright (c) 1998-2004 Michael Shalayeff @@ -2771,171 +2771,23 @@ $spstrcpy_exit copy r0, ret0 EXIT(spstrcpy) - .import whichqs, data - .import qs, data /* - * setrunqueue(struct proc *p); - * Insert a process on the appropriate queue. Should be called at splclock(). + * int cpu_switchto(struct proc *old, struct proc *new) + * Switch from "old" proc to "new". */ .align 32 -ENTRY(setrunqueue,0) -#ifdef DIAGNOSTIC - ldw P_BACK(arg0), t1 - comb,<>,n r0, t1, Lsetrunqueue_panic - ldw P_WCHAN(arg0), t1 - comb,<>,n r0, t1, Lsetrunqueue_panic - ldb P_STAT(arg0), t1 - comib,=,n SRUN, t1, Lsetrunqueue_ok -Lsetrunqueue_panic - copy arg0, arg1 - ldil L%panic, r1 - ldil L%Lsrqpstr, arg0 - ldo R%panic(r1), r1 - ldo R%Lsrqpstr(arg0), arg0 - .call - blr %r0, rp - bv,n %r0(r1) - nop -Lsrqpstr - .asciz "setrunqueue(%p)" - .align 8 -Lsetrunqueue_ok -#endif - - ldb P_PRIORITY(arg0), t2 - ldil L%qs, t4 - extru t2, 29, 5, t1 - ldo R%qs(t4), t4 - sh3add t1, t4, t4 - ldil L%whichqs, arg3 - ldw P_BACK(t4), t2 - stw t4, P_FORW(arg0) - stw arg0, P_BACK(t4) - ldw R%whichqs(arg3), t3 - stw arg0, P_FORW(t2) - mtctl t1, sar - stw t2, P_BACK(arg0) - vdepi 1, 1, t3 - bv 0(rp) - stw t3, R%whichqs(arg3) -EXIT(setrunqueue) - -/* - * remrunqueue(struct proc *p); - * Remove a process from its queue. Should be called at splclock(). - */ - .align 32 -ENTRY(remrunqueue,0) - ldb P_PRIORITY(arg0), t2 - extru t2, 29, 5, arg2 - ldil L%whichqs, t2 - mtsar arg2 - ldw R%whichqs(t2), t3 - -#ifdef DIAGNOSTIC - bvb,<,n t3, remrunqueue_ok - -Lremrunqueue_panic - copy arg0, arg1 - ldil L%panic, r1 - ldil L%Lrrqpstr, arg0 - ldo R%panic(r1), r1 - ldo R%Lrrqpstr(arg0), arg0 - .call - blr %r0, rp - bv,n %r0(r1) - nop - -Lrrqpstr - .asciz "remrunqueue(%p), bit=%x" - .align 8 -remrunqueue_ok -#endif - ldw P_BACK(arg0), t4 - stw r0, P_BACK(arg0) - ldw P_FORW(arg0), arg0 - stw arg0, P_FORW(t4) - vdepi 0, 1, t3 - sub,<> t4, arg0, r0 - stw t3, R%whichqs(t2) - bv 0(rp) - stw t4, P_BACK(arg0) -EXIT(remrunqueue) - -/* - * cpu_switch() - * Find the highest priority process and resume it. - */ - .align 32 -ENTRY(cpu_switch,128) - ldil L%cpl, t1 - ldw R%cpl(t1), ret0 +ENTRY(cpu_switchto,128) copy r3, r1 stw rp, HPPA_FRAME_CRP(sp) copy sp, r3 - stw ret0, HPPA_FRAME_SL(sp) stwm r1, HPPA_FRAME_SIZE+20*4(sp) - /* - * Clear curproc so that we don't accumulate system time while idle. - */ - ldil L%curproc, t1 - ldw R%curproc(t1), arg2 - b switch_search - stw r0, R%curproc(t1) - /* remain on the old (curproc)'s stack until we have a better choice */ - -cpu_idle - copy r0, arg0 - break HPPA_BREAK_KERNEL, HPPA_BREAK_SPLLOWER - .import uvm, data - ldil L%(uvm + PAGE_IDLE_ZERO), t3 - ldw R%(uvm + PAGE_IDLE_ZERO)(t3), t4 - sub,<> r0, t4, r0 - b cpu_loop - - stw arg2, 4(r3) - ldil L%uvm_pageidlezero, t1 - ldo R%uvm_pageidlezero(t1), t2 - .call - ble 0(sr0, t2) - copy r31, rp - - ldw HPPA_FRAME_SL(r3), ret0 - ldw 4(r3), arg2 - -cpu_loop - ldil L%cpl, arg0 - stw ret0, R%cpl(arg0) - -switch_search - /* - * t1: &whichqs - * arg2: old curproc - * - */ - ldil L%whichqs, t1 - ldw R%whichqs(t1), t3 - comb,=,n r0, t3, cpu_idle - copy r0, arg0 - - ldi 0, t4 -getbit - mtsar t4 - bvb,>=,n t3, getbit - ldo 1(t4), t4 - - ldil L%qs, t2 - ldo R%qs(t2), t2 - sh3add t4, t2, t2 - - ldw P_FORW(t2), arg1 #ifdef DIAGNOSTIC - comb,<> t2, arg1, link_ok + b kstack_check nop switch_error - copy t4, arg1 - copy t2, arg2 + copy arg1, arg2 + copy arg0, arg1 ldil L%panic, r1 ldil L%Lcspstr, arg0 ldo R%panic(r1), r1 @@ -2945,61 +2797,48 @@ switch_error bv,n %r0(r1) nop Lcspstr - .asciz "cpu_switch: bit=%x, q/p=%p" + .asciz "cpu_switch:old=%p, new=%p" .align 8 -link_ok -#endif - ldil L%want_resched, t4 - stw r0, R%want_resched(t4) - - ldw P_FORW(arg1), arg0 - stw arg0, P_FORW(t2) - stw t2, P_BACK(arg0) - stw r0, P_BACK(arg1) - - vdepi 0, 1, t3 - sub,<> t2, arg0, r0 - stw t3, R%whichqs(t1) - - /* don't need &whichqs (t1) starting here */ -#ifdef DIAGNOSTIC +kstack_check ldw P_WCHAN(arg1), t1 comb,<>,n r0, t1, switch_error - copy arg1, t2 + nop ldb P_STAT(arg1), t1 comib,<>,n SRUN, t1, switch_error - copy arg1, t2 + nop /* - * Either we must be switching to the same process, or - * the new process' kernel stack must be reasonable. + * The new process' kernel stack must be reasonable. */ - comb,=,n arg1, arg2, kstack_ok - ldw P_ADDR(arg1), arg0 - ldw U_PCB+PCB_KSP(arg0), t1 - ldo NBPG(arg0), arg0 - comb,>>,n arg0, t1, switch_error - copy arg1, t2 - sub t1, arg0, t1 - ldil L%USPACE, arg0 - ldo R%USPACE(arg0), arg0 - comb,<<=,n arg0, t1, switch_error - copy arg1, t2 + ldw P_ADDR(arg1), arg2 + ldw U_PCB+PCB_KSP(arg2), t1 + ldo NBPG(arg2), arg2 + comb,>>,n arg2, t1, switch_error + nop + sub t1, arg2, t1 + ldil L%USPACE, arg2 + ldo R%USPACE(arg2), arg2 + comb,<<=,n arg2, t1, switch_error + nop kstack_ok #endif + ldil L%want_resched, t4 + stw r0, R%want_resched(t4) + + /* Record new proc. */ ldi SONPROC, t1 stb t1, P_STAT(arg1) - /* Skip context switch if same process. */ - comb,=,n arg1, arg2, switch_return + ldil L%curproc, t1 + stw arg1, R%curproc(t1) /* If old process exited, don't bother. */ - comb,=,n r0, arg2, switch_exited + comb,=,n r0, arg0, switch_exited /* * 2. save old proc context * - * arg2: old proc + * arg0: old proc */ - ldw P_ADDR(arg2), t1 + ldw P_ADDR(arg0), t1 /* save callee-save registers */ stw r4, 1*4(r3) stw sp, U_PCB+PCB_KSP(t1) @@ -3021,13 +2860,14 @@ kstack_ok stw r0, HPPA_FRAME_ARG(1)(sp) /* say no trampoline */ sync - /* don't need old curproc (arg2) starting from here */ + /* don't need old curproc (arg0) starting from here */ switch_exited /* * 3. restore new proc context * * arg1: new proc */ + /* XXX disable interrupts? */ ldw P_ADDR(arg1), t2 ldw P_MD_REGS(arg1), t1 ldw U_PCB+PCB_KSP(t2), sp @@ -3036,11 +2876,12 @@ switch_exited ldw TF_CR9(t1), t3 mtctl t2, cr30 mtctl t3, pidr2 + /* XXX enable interrupts? */ ldo -(HPPA_FRAME_SIZE+20*4)(sp), r3 ldw HPPA_FRAME_ARG(0)(sp), arg0 ldw HPPA_FRAME_ARG(1)(sp), t4 /* in case we're on trampoline */ sub,= r0, t4, r0 - b switch_gonnajump + b switch_return ldw 1*4(r3), r4 ldw 2*4(r3), r5 ldw 3*4(r3), r6 @@ -3056,21 +2897,31 @@ switch_exited ldw 13*4(r3), r16 ldw 14*4(r3), r17 ldw 15*4(r3), r18 -switch_gonnajump - ldw HPPA_FRAME_SL(r3), ret0 - ldil L%cpl, t1 - stw ret0, R%cpl(t1) - sync switch_return - ldil L%curproc, t1 - stw arg1, R%curproc(t1) ldw HPPA_FRAME_CRP(r3), rp bv 0(rp) ldwm -(HPPA_FRAME_SIZE+20*4)(sp), r3 -EXIT(cpu_switch) +EXIT(cpu_switchto) + +LEAF_ENTRY(cpu_idle_enter) + bv 0(rp) + nop +EXIT(cpu_idle_enter) + +LEAF_ENTRY(cpu_idle_cycle) + bv 0(rp) + nop +EXIT(cpu_idle_cycle) + +LEAF_ENTRY(cpu_idle_leave) + bv 0(rp) + nop +EXIT(cpu_idle_leave) ENTRY(switch_trampoline,0) + ldil L%cpl, t1 + stw r0, R%cpl(t1) .call blr r0, rp bv,n r0(t4) diff --git a/sys/arch/hppa/hppa/vm_machdep.c b/sys/arch/hppa/hppa/vm_machdep.c index a4b8e0f5d5a..528a1dba26c 100644 --- a/sys/arch/hppa/hppa/vm_machdep.c +++ b/sys/arch/hppa/hppa/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.61 2007/06/20 17:29:34 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.62 2007/10/10 15:53:51 art Exp $ */ /* * Copyright (c) 1999-2004 Michael Shalayeff @@ -160,12 +160,11 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) tf->tf_sp = (register_t)stack; /* - * Build stack frames for the cpu_switch & co. + * Build stack frames for the cpu_switchto & co. */ osp = sp + HPPA_FRAME_SIZE; *(register_t*)(osp - HPPA_FRAME_SIZE) = 0; *(register_t*)(osp + HPPA_FRAME_CRP) = (register_t)&switch_trampoline; - *(register_t*)(osp + HPPA_FRAME_SL) = 0; /* cpl */ *(register_t*)(osp) = (osp - HPPA_FRAME_SIZE); sp = osp + HPPA_FRAME_SIZE + 20*4; /* frame + calee-save registers */ @@ -187,8 +186,8 @@ cpu_exit(p) fpu_curpcb = 0; } - exit2(p); - cpu_switch(p); + pmap_deactivate(p); + sched_exit(p); } void diff --git a/sys/arch/hppa/include/cpu.h b/sys/arch/hppa/include/cpu.h index 58586ebc26a..ff9f6aa916c 100644 --- a/sys/arch/hppa/include/cpu.h +++ b/sys/arch/hppa/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.51 2007/07/20 22:12:39 kettenis Exp $ */ +/* $OpenBSD: cpu.h,v 1.52 2007/10/10 15:53:51 art Exp $ */ /* * Copyright (c) 2000-2004 Michael Shalayeff @@ -64,6 +64,7 @@ #ifndef _LOCORE #ifdef _KERNEL +#include <sys/queue.h> #include <sys/sched.h> struct cpu_info { diff --git a/sys/arch/i386/i386/cpu.c b/sys/arch/i386/i386/cpu.c index 726f3e816bb..6e9202f114b 100644 --- a/sys/arch/i386/i386/cpu.c +++ b/sys/arch/i386/i386/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.25 2007/05/29 18:18:20 tom Exp $ */ +/* $OpenBSD: cpu.c,v 1.26 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: cpu.c,v 1.1.2.7 2000/06/26 02:04:05 sommerfeld Exp $ */ /*- @@ -295,6 +295,7 @@ cpu_attach(struct device *parent, struct device *self, void *aux) cpu_alloc_ldt(ci); ci->ci_flags |= CPUF_PRESENT | CPUF_AP; identifycpu(ci); + sched_init_cpu(ci); ci->ci_next = cpu_info_list->ci_next; cpu_info_list->ci_next = ci; ncpus++; @@ -463,6 +464,9 @@ cpu_hatch(void *v) ci->ci_dev.dv_xname, ci->ci_cpuid); microuptime(&ci->ci_schedstate.spc_runtime); splx(s); + + SCHED_LOCK(s); + cpu_switchto(NULL, sched_chooseproc()); } void diff --git a/sys/arch/i386/i386/genassym.cf b/sys/arch/i386/i386/genassym.cf index 88c086d6526..211a677dfa5 100644 --- a/sys/arch/i386/i386/genassym.cf +++ b/sys/arch/i386/i386/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.27 2007/10/03 07:51:26 kettenis Exp $ +# $OpenBSD: genassym.cf,v 1.28 2007/10/10 15:53:51 art Exp $ # # Copyright (c) 1982, 1990 The Regents of the University of California. # All rights reserved. @@ -88,8 +88,6 @@ export VM_MAXUSER_ADDRESS # proc fields and values struct proc member p_addr -member p_back -member p_forw member p_priority member p_stat member p_wchan diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s index d8e379cb506..ff5a97e22ce 100644 --- a/sys/arch/i386/i386/locore.s +++ b/sys/arch/i386/i386/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.115 2007/10/03 07:51:26 kettenis Exp $ */ +/* $OpenBSD: locore.s,v 1.116 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */ /*- @@ -1295,279 +1295,52 @@ ENTRY(longjmp) ret /*****************************************************************************/ - -/* - * The following primitives manipulate the run queues. - * whichqs tells which of the 32 queues qs have processes in them. - * Setrq puts processes into queues, Remrq removes them from queues. - * The running process is on no queue, other processes are on a queue - * related to p->p_pri, divided by 4 actually to shrink the 0-127 range - * of priorities into the 32 available queues. - */ - .globl _C_LABEL(whichqs),_C_LABEL(qs),_C_LABEL(uvmexp),_C_LABEL(panic) -/* - * setrunqueue(struct proc *p); - * Insert a process on the appropriate queue. Should be called at splclock(). - */ -NENTRY(setrunqueue) - movl 4(%esp),%eax -#ifdef DIAGNOSTIC - cmpl $0,P_BACK(%eax) # should not be on q already - jne 1f - cmpl $0,P_WCHAN(%eax) - jne 1f - cmpb $SRUN,P_STAT(%eax) - jne 1f -#endif /* DIAGNOSTIC */ - movzbl P_PRIORITY(%eax),%edx - shrl $2,%edx - btsl %edx,_C_LABEL(whichqs) # set q full bit - leal _C_LABEL(qs)(,%edx,8),%edx # locate q hdr - movl P_BACK(%edx),%ecx - movl %edx,P_FORW(%eax) # link process on tail of q - movl %eax,P_BACK(%edx) - movl %eax,P_FORW(%ecx) - movl %ecx,P_BACK(%eax) - ret -#ifdef DIAGNOSTIC -1: pushl $2f - call _C_LABEL(panic) - /* NOTREACHED */ -2: .asciz "setrunqueue" -#endif /* DIAGNOSTIC */ - -/* - * remrunqueue(struct proc *p); - * Remove a process from its queue. Should be called at splclock(). - */ -NENTRY(remrunqueue) - movl 4(%esp),%ecx - movzbl P_PRIORITY(%ecx),%eax -#ifdef DIAGNOSTIC - shrl $2,%eax - btl %eax,_C_LABEL(whichqs) - jnc 1f -#endif /* DIAGNOSTIC */ - movl P_BACK(%ecx),%edx # unlink process - movl $0,P_BACK(%ecx) # zap reverse link to indicate off list - movl P_FORW(%ecx),%ecx - movl %ecx,P_FORW(%edx) - movl %edx,P_BACK(%ecx) - cmpl %ecx,%edx # q still has something? - jne 2f -#ifndef DIAGNOSTIC - shrl $2,%eax -#endif - btrl %eax,_C_LABEL(whichqs) # no; clear bit -2: ret + #ifdef DIAGNOSTIC -1: pushl $3f +NENTRY(switch_error1) + pushl %edi + pushl $1f call _C_LABEL(panic) /* NOTREACHED */ -3: .asciz "remrunqueue" -#endif /* DIAGNOSTIC */ - -#if NAPM > 0 - .globl _C_LABEL(apm_cpu_idle),_C_LABEL(apm_cpu_busy) -#endif -/* - * When no processes are on the runq, cpu_switch() branches to here to wait for - * something to come ready. - */ -ENTRY(idle) - /* Skip context saving if we have none. */ - testl %esi,%esi - jz 1f - - /* - * idling: save old context. - * - * Registers: - * %eax, %ebx, %ecx - scratch - * %esi - old proc, then old pcb - * %edi - idle pcb - * %edx - idle TSS selector - */ - - pushl %esi - call _C_LABEL(pmap_deactivate) # pmap_deactivate(oldproc) - addl $4,%esp - - movl P_ADDR(%esi),%esi - - /* Save stack pointers. */ - movl %esp,PCB_ESP(%esi) - movl %ebp,PCB_EBP(%esi) - - /* Find idle PCB for this CPU */ -#ifndef MULTIPROCESSOR - movl $_C_LABEL(proc0),%ebx - movl P_ADDR(%ebx),%edi - movl P_MD_TSS_SEL(%ebx),%edx -#else - movl CPUVAR(IDLE_PCB), %edi - movl CPUVAR(IDLE_TSS_SEL), %edx -#endif - - /* Restore the idle context (avoid interrupts) */ - cli - - /* Restore stack pointers. */ - movl PCB_ESP(%edi),%esp - movl PCB_EBP(%edi),%ebp - - - /* Switch address space. */ - movl PCB_CR3(%edi),%ecx - movl %ecx,%cr3 - - /* Switch TSS. Reset "task busy" flag before loading. */ - movl CPUVAR(GDT), %eax - andl $~0x0200,4-SEL_KPL(%eax,%edx,1) - ltr %dx - - /* We're always in the kernel, so we don't need the LDT. */ - - /* Restore cr0 (including FPU state). */ - movl PCB_CR0(%edi),%ecx - movl %ecx,%cr0 - - /* Record new pcb. */ - SET_CURPCB(%edi) - - xorl %esi,%esi - sti - -1: -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_unlock_idle) -#endif - - movl $IPL_NONE,CPL # spl0() - call _C_LABEL(Xspllower) # process pending interrupts - jmp _C_LABEL(idle_start) - -ENTRY(idle_loop) -#if NAPM > 0 - call _C_LABEL(apm_cpu_idle) -#else -#if NPCTR > 0 - addl $1,_C_LABEL(pctr_idlcnt) - adcl $0,_C_LABEL(pctr_idlcnt)+4 -#endif - sti - hlt -#endif -ENTRY(idle_start) - cli - cmpl $0,_C_LABEL(whichqs) - jz _C_LABEL(idle_loop) - -ENTRY(idle_exit) - movl $IPL_HIGH,CPL # splhigh - sti -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_lock_idle) -#endif -#if NAPM > 0 - call _C_LABEL(apm_cpu_busy) -#endif - jmp switch_search - -#ifdef DIAGNOSTIC -NENTRY(switch_error) +1: .asciz "cpu_switch1 %p" +NENTRY(switch_error2) + pushl %edi pushl $1f call _C_LABEL(panic) /* NOTREACHED */ -1: .asciz "cpu_switch" +1: .asciz "cpu_switch2 %p" #endif /* DIAGNOSTIC */ /* - * cpu_switch(void); - * Find a runnable process and switch to it. Wait if necessary. If the new - * process is the same as the old one, we short-circuit the context save and - * restore. + * cpu_switchto(struct proc *old, struct proc *new) + * Switch from the "old" proc to the "new" proc. If "old" is NULL, we + * don't need to bother saving old context. */ -ENTRY(cpu_switch) +ENTRY(cpu_switchto) pushl %ebx pushl %esi pushl %edi - pushl CPL - - movl CPUVAR(CURPROC), %esi - - /* - * Clear curproc so that we don't accumulate system time while idle. - * This also insures that schedcpu() will move the old process to - * the correct queue if it happens to get called from the spllower() - * below and changes the priority. (See corresponding comment in - * userret()). - */ - movl $0, CPUVAR(CURPROC) - -switch_search: - /* - * First phase: find new process. - * - * Registers: - * %eax - queue head, scratch, then zero - * %ebx - queue number - * %ecx - cached value of whichqs - * %edx - next process in queue - * %esi - old process - * %edi - new process - */ - /* Wait for new process. */ - movl _C_LABEL(whichqs),%ecx - bsfl %ecx,%ebx # find a full q - jz _C_LABEL(idle) # if none, idle - leal _C_LABEL(qs)(,%ebx,8),%eax # select q - movl P_FORW(%eax),%edi # unlink from front of process q -#ifdef DIAGNOSTIC - cmpl %edi,%eax # linked to self (i.e. nothing queued)? - je _C_LABEL(switch_error) # not possible -#endif /* DIAGNOSTIC */ - movl P_FORW(%edi),%edx - movl %edx,P_FORW(%eax) - movl %eax,P_BACK(%edx) + movl 16(%esp), %esi + movl 20(%esp), %edi - cmpl %edx,%eax # q empty? - jne 3f - - btrl %ebx,%ecx # yes, clear to indicate empty - movl %ecx,_C_LABEL(whichqs) # update q status + xorl %eax, %eax -3: xorl %eax, %eax - /* We just did it. */ - movl $0, CPUVAR(RESCHED) + movl %eax, CPUVAR(RESCHED) #ifdef DIAGNOSTIC cmpl %eax,P_WCHAN(%edi) # Waiting for something? - jne _C_LABEL(switch_error) # Yes; shouldn't be queued. + jne _C_LABEL(switch_error1) # Yes; shouldn't be queued. cmpb $SRUN,P_STAT(%edi) # In run state? - jne _C_LABEL(switch_error) # No; shouldn't be queued. + jne _C_LABEL(switch_error2) # No; shouldn't be queued. #endif /* DIAGNOSTIC */ - /* Isolate process. XXX Is this necessary? */ - movl %eax,P_BACK(%edi) - - /* Record new process. */ - movb $SONPROC,P_STAT(%edi) # p->p_stat = SONPROC - movl CPUVAR(SELF), %ecx - movl %edi, CPUVAR(CURPROC) - movl %ecx, P_CPU(%edi) - - /* Skip context switch if same process. */ - cmpl %edi,%esi - je switch_return - /* If old process exited, don't bother. */ testl %esi,%esi jz switch_exited /* - * Second phase: save old context. + * Save old context. * * Registers: * %eax, %ecx - scratch @@ -1597,18 +1370,19 @@ switch_exited: /* No interrupts while loading new state. */ cli + + /* Record new process. */ + movl CPUVAR(SELF), %ebx + movl %edi, CPUVAR(CURPROC) + movb $SONPROC, P_STAT(%edi) + movl %ebx, P_CPU(%edi) + movl P_ADDR(%edi),%esi /* Restore stack pointers. */ movl PCB_ESP(%esi),%esp movl PCB_EBP(%esi),%ebp -#if 0 - /* Don't bother with the rest if switching to a system process. */ - testl $P_SYSTEM,P_FLAG(%edi) - jnz switch_restored -#endif - /* * Activate the address space. We're curproc, so %cr3 will * be reloaded, but we're not yet curpcb, so the LDT won't @@ -1639,7 +1413,6 @@ switch_exited: lldt %dx #endif /* USER_LDT */ -switch_restored: /* Restore cr0 (including FPU state). */ movl PCB_CR0(%esi),%ecx #ifdef MULTIPROCESSOR @@ -1661,103 +1434,29 @@ switch_restored: /* Interrupts are okay again. */ sti -switch_return: -#if 0 - pushl %edi - movl CPUVAR(NAME), %ebx - leal CPU_INFO_NAME(%ebx),%ebx - pushl %ebx - pushl $1f - call _C_LABEL(printf) - addl $0xc,%esp -#endif -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_unlock_idle) -#endif - /* - * Restore old cpl from stack. Note that this is always an increase, - * due to the spl0() on entry. - */ - popl CPL - - movl %edi,%eax # return (p); popl %edi popl %esi popl %ebx ret -1: .asciz "%s: scheduled %x\n" -/* - * switch_exit(struct proc *p); - * Switch to the appropriate idle context (proc0's if uniprocessor; the cpu's if - * multiprocessor) and deallocate the address space and kernel stack for p. - * Then jump into cpu_switch(), as if we were in the idle proc all along. - */ -#ifndef MULTIPROCESSOR - .globl _C_LABEL(proc0) -#endif -ENTRY(switch_exit) - movl 4(%esp),%edi # old process -#ifndef MULTIPROCESSOR - movl $_C_LABEL(proc0),%ebx - movl P_ADDR(%ebx),%esi - movl P_MD_TSS_SEL(%ebx),%edx -#else - movl CPUVAR(IDLE_PCB), %esi - movl CPUVAR(IDLE_TSS_SEL), %edx -#endif - - /* In case we fault... */ - movl $0, CPUVAR(CURPROC) - - /* Restore the idle context. */ - cli - - /* Restore stack pointers. */ - movl PCB_ESP(%esi),%esp - movl PCB_EBP(%esi),%ebp - - /* Load TSS info. */ - movl CPUVAR(GDT), %eax - - /* Switch address space. */ - movl PCB_CR3(%esi),%ecx - movl %ecx,%cr3 - - /* Switch TSS. */ - andl $~0x0200,4-SEL_KPL(%eax,%edx,1) - ltr %dx - /* We're always in the kernel, so we don't need the LDT. */ - - /* Clear segment registers; always null in proc0. */ - xorl %ecx,%ecx - movw %cx,%gs - - /* Point to cpu_info */ - movl $GSEL(GCPU_SEL, SEL_KPL),%ecx - movw %cx,%fs - - /* Restore cr0 (including FPU state). */ - movl PCB_CR0(%esi),%ecx - movl %ecx,%cr0 - - /* Record new pcb. */ - SET_CURPCB(%esi) +ENTRY(cpu_idle_enter) + ret - /* Interrupts are okay again. */ +ENTRY(cpu_idle_cycle) +#if NAPM > 0 + call _C_LABEL(apm_cpu_idle) +#else +#if NPCTR > 0 + addl $1,_C_LABEL(pctr_idlcnt) + adcl $0,_C_LABEL(pctr_idlcnt)+4 +#endif sti + hlt +#endif + ret - /* - * Schedule the dead process's vmspace and stack to be freed. - */ - pushl %edi /* exit2(p) */ - call _C_LABEL(exit2) - addl $4,%esp - - /* Jump into cpu_switch() with the right state. */ - xorl %esi,%esi - movl $0, CPUVAR(CURPROC) - jmp switch_search +ENTRY(cpu_idle_leave) + ret /* * savectx(struct pcb *pcb); diff --git a/sys/arch/i386/i386/mptramp.s b/sys/arch/i386/i386/mptramp.s index b68ec50ed12..de120c4de55 100644 --- a/sys/arch/i386/i386/mptramp.s +++ b/sys/arch/i386/i386/mptramp.s @@ -1,4 +1,4 @@ -/* $OpenBSD: mptramp.s,v 1.8 2007/02/20 21:15:01 tom Exp $ */ +/* $OpenBSD: mptramp.s,v 1.9 2007/10/10 15:53:51 art Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -249,9 +249,7 @@ mp_cont: HALTT(0x30,%ecx) pushl %ecx call _C_LABEL(cpu_hatch) - HALT(0x33) - xorl %esi,%esi - jmp _C_LABEL(idle_start) + /* NOTREACHED */ .data _C_LABEL(mp_pdirpa): diff --git a/sys/arch/i386/i386/vm_machdep.c b/sys/arch/i386/i386/vm_machdep.c index 4f969a96aaa..a12b279cfb1 100644 --- a/sys/arch/i386/i386/vm_machdep.c +++ b/sys/arch/i386/i386/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.52 2007/05/27 20:59:25 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.53 2007/10/10 15:53:51 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.61 1996/05/03 19:42:35 christos Exp $ */ /*- @@ -126,7 +126,6 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, tf->tf_esp = (u_int)stack + stacksize; sf = (struct switchframe *)tf - 1; - sf->sf_ppl = 0; sf->sf_esi = (int)func; sf->sf_ebx = (int)arg; sf->sf_eip = (int)proc_trampoline; @@ -151,7 +150,7 @@ cpu_exit(struct proc *p) #endif pmap_deactivate(p); - switch_exit(p); + sched_exit(p); } void diff --git a/sys/arch/i386/include/frame.h b/sys/arch/i386/include/frame.h index 8ce02c8753f..cc1263e57c8 100644 --- a/sys/arch/i386/include/frame.h +++ b/sys/arch/i386/include/frame.h @@ -1,4 +1,4 @@ -/* $OpenBSD: frame.h,v 1.8 2006/11/27 18:04:28 gwk Exp $ */ +/* $OpenBSD: frame.h,v 1.9 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: frame.h,v 1.12 1995/10/11 04:20:08 mycroft Exp $ */ /*- @@ -106,7 +106,6 @@ struct intrframe { * Stack frame inside cpu_switch() */ struct switchframe { - int sf_ppl; int sf_edi; int sf_esi; int sf_ebx; diff --git a/sys/arch/luna88k/luna88k/locore.S b/sys/arch/luna88k/luna88k/locore.S index 81a5477308a..9f8e0ec9a2e 100644 --- a/sys/arch/luna88k/luna88k/locore.S +++ b/sys/arch/luna88k/luna88k/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.13 2007/01/12 21:41:53 aoyama Exp $ */ +/* $OpenBSD: locore.S,v 1.14 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -150,8 +150,8 @@ ASLOCAL(main_start) * Now we will compete with the other processors to see which one * will be elected as the main one. */ - or.u r11, r0, hi16(_ASM_LABEL(cpu_mutex)) - or r11, r11, lo16(_ASM_LABEL(cpu_mutex)) + or.u r11, r0, hi16(_C_LABEL(cpu_mutex)) + or r11, r11, lo16(_C_LABEL(cpu_mutex)) 1: FLUSH_PIPELINE or r22, r0, 1 @@ -282,15 +282,6 @@ ASLOCAL(secondary_init) bsr.n _C_LABEL(secondary_pre_main) /* set cpu number */ or r31, r31, lo16(_ASM_LABEL(slavestack_end)) - /* - * Release cpu_mutex; we have a race with other secondary CPUs here - * because the stack has not been switched yet. However, since our - * interrupts are disabled, the worst we can get is an NMI, and, oh - * well, it means we're in deep trouble anyway. - */ - or.u r10, r0, hi16(_ASM_LABEL(cpu_mutex)) - st r0, r10, lo16(_ASM_LABEL(cpu_mutex)) - ldcr r2, CPU 1: ld r3, r2, CI_CURPCB @@ -299,13 +290,6 @@ ASLOCAL(secondary_init) br.n _C_LABEL(secondary_main) add r31, r3, USIZE /* switch to idle stack */ - /* - * At this point, the CPU has been correctly initialized and has - * identified itself on the console. - * All it needs now is to jump to the idle loop and wait for work to - * be offered. - */ - br _ASM_LABEL(cpu_switch_search) #else /* @@ -315,15 +299,6 @@ ASLOCAL(secondary_init) #endif /* MULTIPROCESSOR */ - /* - * Release the cpu_mutex; secondary processors will now have their - * chance to initialize. - */ -GLOBAL(cpu_boot_secondary_processors) - or.u r2, r0, hi16(_ASM_LABEL(cpu_mutex)) - jmp.n r1 - st r0, r2, lo16(_ASM_LABEL(cpu_mutex)) - /* * void delay(int count) * @@ -384,10 +359,6 @@ GLOBAL(proc0paddr) ASLOCAL(master_mpu) word 0 -/* XMEM spin lock -- controls access to master_mpu */ -ASLOCAL(cpu_mutex) - word 0 - #if defined(DDB) || NKSYMS > 0 GLOBAL(esym) word 0 diff --git a/sys/arch/luna88k/luna88k/machdep.c b/sys/arch/luna88k/luna88k/machdep.c index 0a40e973bd7..bc12f69d4fb 100644 --- a/sys/arch/luna88k/luna88k/machdep.c +++ b/sys/arch/luna88k/luna88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.44 2007/06/06 17:15:12 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.45 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -85,6 +85,7 @@ #include <machine/cmmu.h> #include <machine/cpu.h> #include <machine/kcore.h> +#include <machine/lock.h> #include <machine/reg.h> #include <machine/trap.h> #include <machine/m88100.h> @@ -105,6 +106,7 @@ caddr_t allocsys(caddr_t); void consinit(void); +void cpu_boot_secondary_processors(void); void dumpconf(void); void dumpsys(void); int getcpuspeed(void); @@ -183,6 +185,8 @@ int physmem; /* available physical memory, in pages */ struct vm_map *exec_map = NULL; struct vm_map *phys_map = NULL; +__cpu_simple_lock_t cpu_mutex = __SIMPLELOCK_UNLOCKED; + /* * Declare these as initialized data so we can patch them. */ @@ -756,6 +760,16 @@ abort: #ifdef MULTIPROCESSOR /* + * Release the cpu_mutex; secondary processors will now have their + * chance to initialize. + */ +void +cpu_boot_secondary_processors() +{ + __cpu_simple_unlock(&cpu_mutex); +} + +/* * Secondary CPU early initialization routine. * Determine CPU number and set it, then allocate the idle pcb (and stack). * @@ -793,17 +807,18 @@ void secondary_main() { struct cpu_info *ci = curcpu(); + int s; cpu_configuration_print(0); + sched_init_cpu(ci); ncpus++; + __cpu_simple_unlock(&cpu_mutex); microuptime(&ci->ci_schedstate.spc_runtime); + ci->ci_curproc = NULL; - /* - * Upon return, the secondary cpu bootstrap code in locore will - * enter the idle loop, waiting for some food to process on this - * processor. - */ + SCHED_LOCK(s); + cpu_switchto(NULL, sched_chooseproc()); } #endif /* MULTIPROCESSOR */ @@ -966,7 +981,6 @@ luna88k_bootstrap() cpuid_t cpu; extern void m8820x_initialize_cpu(cpuid_t); extern void m8820x_set_sapr(cpuid_t, apr_t); - extern void cpu_boot_secondary_processors(void); cmmu = &cmmu8820x; diff --git a/sys/arch/m68k/include/cpu.h b/sys/arch/m68k/include/cpu.h index 9a88a3d80ea..9b3843e760e 100644 --- a/sys/arch/m68k/include/cpu.h +++ b/sys/arch/m68k/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.17 2007/05/22 10:31:08 martin Exp $ */ +/* $OpenBSD: cpu.h,v 1.18 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: cpu.h,v 1.3 1997/02/02 06:56:57 thorpej Exp $ */ /* @@ -66,6 +66,7 @@ #ifdef _KERNEL #ifndef _LOCORE +#include <sys/queue.h> #include <sys/sched.h> struct cpu_info { @@ -269,6 +270,9 @@ int cachectl(struct proc *, int, vaddr_t, int); */ #define PROC_PC(p) (((struct trapframe *)((p)->p_md.md_regs))->tf_pc) +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_leave() do { /* nothing */ } while (0) + #endif /* _KERNEL */ #endif /* _M68K_CPU_H_ */ diff --git a/sys/arch/m68k/m68k/genassym.cf b/sys/arch/m68k/m68k/genassym.cf index d608d7fa85b..05ce97c1a37 100644 --- a/sys/arch/m68k/m68k/genassym.cf +++ b/sys/arch/m68k/m68k/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.12 2007/05/15 13:46:22 martin Exp $ +# $OpenBSD: genassym.cf,v 1.13 2007/10/10 15:53:52 art Exp $ # # Copyright (c) 1995 Theo de Raadt @@ -71,15 +71,10 @@ export NBPG # proc fields and values struct proc -member p_forw -member p_back -member p_priority member p_stat -member p_wchan member p_vmspace member p_addr -export SRUN export SONPROC # contexts diff --git a/sys/arch/m68k/m68k/proc_subr.s b/sys/arch/m68k/m68k/proc_subr.s index 23d3f4d61b8..e69de29bb2d 100644 --- a/sys/arch/m68k/m68k/proc_subr.s +++ b/sys/arch/m68k/m68k/proc_subr.s @@ -1,129 +0,0 @@ -/* $OpenBSD: proc_subr.s,v 1.2 2003/06/02 23:27:48 millert Exp $ */ -/* $NetBSD: proc_subr.s,v 1.2 1997/04/25 02:22:01 thorpej Exp $ */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1980, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department. - * - * 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. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * from: Utah $Hdr: locore.s 1.66 92/12/22$ - * - * @(#)locore.s 8.6 (Berkeley) 5/27/94 - */ - -/* - * Assembly routines related to process manipulation. - */ - -/* - * NOTICE: This is not a standalone file. To use it, #include it in - * your port's locore.s, like so: - * - * #include <m68k/m68k/proc_subr.s> - */ - -/* - * The following primitives manipulate the run queues. _whichqs tells which - * of the 32 queues _qs have processes in them. Setrunqueue puts processes - * into queues, remrunqueue removes them from queues. The running process is - * on no queue, other processes are on a queue related to p->p_priority, - * divided by 4 actually to shrink the 0-127 range of priorities into the 32 - * available queues. - */ - -/* - * Setrunqueue(p) - * - * Call should be made at spl6(), and p->p_stat should be SRUN - */ -ENTRY(setrunqueue) - movl sp@(4),a0 -#ifdef DIAGNOSTIC - tstl a0@(P_BACK) - jne Lset1 - tstl a0@(P_WCHAN) - jne Lset1 - cmpb #SRUN,a0@(P_STAT) - jne Lset1 -#endif - clrl d0 - movb a0@(P_PRIORITY),d0 - lsrb #2,d0 - movl _C_LABEL(whichqs),d1 - bset d0,d1 - movl d1,_C_LABEL(whichqs) - lslb #3,d0 - addl #_C_LABEL(qs),d0 - movl d0,a0@(P_FORW) - movl d0,a1 - movl a1@(P_BACK),a0@(P_BACK) - movl a0,a1@(P_BACK) - movl a0@(P_BACK),a1 - movl a0,a1@(P_FORW) - rts -#ifdef DIAGNOSTIC -Lset1: - PANIC("setrunqueue") -#endif - -/* - * remrunqueue(p) - * - * Call should be made at spl6(). - */ -ENTRY(remrunqueue) - movl sp@(4),a0 - movb a0@(P_PRIORITY),d0 -#ifdef DIAGNOSTIC - lsrb #2,d0 - movl _C_LABEL(whichqs),d1 - btst d0,d1 - jeq Lrem2 -#endif - movl a0@(P_BACK),a1 - clrl a0@(P_BACK) - movl a0@(P_FORW),a0 - movl a0,a1@(P_FORW) - movl a1,a0@(P_BACK) - cmpal a0,a1 - jne Lrem1 -#ifndef DIAGNOSTIC - lsrb #2,d0 - movl _C_LABEL(whichqs),d1 -#endif - bclr d0,d1 - movl d1,_C_LABEL(whichqs) -Lrem1: - rts -#ifdef DIAGNOSTIC -Lrem2: - PANIC("remrunqueue") -#endif diff --git a/sys/arch/m88k/include/cpu.h b/sys/arch/m88k/include/cpu.h index 317cc61704f..ab3342c7734 100644 --- a/sys/arch/m88k/include/cpu.h +++ b/sys/arch/m88k/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.22 2007/05/19 20:34:32 miod Exp $ */ +/* $OpenBSD: cpu.h,v 1.23 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1996 Nivas Madhur * Copyright (c) 1992, 1993 @@ -58,6 +58,7 @@ #include <machine/pcb.h> #include <machine/psl.h> #include <machine/intr.h> +#include <sys/queue.h> #include <sys/sched.h> #if defined(MULTIPROCESSOR) @@ -165,6 +166,8 @@ void set_cpu_number(cpuid_t); #define cpu_exec(p) do { /* nothing */ } while (0) #define cpu_wait(p) do { /* nothing */ } while (0) +#define cpu_idle_cycle() do { /* nothing */ } while (0) + #if defined(MULTIPROCESSOR) #include <sys/lock.h> #include <sys/mplock.h> diff --git a/sys/arch/m88k/m88k/genassym.cf b/sys/arch/m88k/m88k/genassym.cf index 5738186c08a..2afe41589d1 100644 --- a/sys/arch/m88k/m88k/genassym.cf +++ b/sys/arch/m88k/m88k/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.8 2007/05/12 19:59:52 miod Exp $ +# $OpenBSD: genassym.cf,v 1.9 2007/10/10 15:53:52 art Exp $ # # Copyright (c) 1982, 1990 The Regents of the University of California. # All rights reserved. @@ -28,7 +28,7 @@ # SUCH DAMAGE. # # @(#)genassym.c 7.8 (Berkeley) 5/7/91 -# $Id: genassym.cf,v 1.8 2007/05/12 19:59:52 miod Exp $ +# $Id: genassym.cf,v 1.9 2007/10/10 15:53:52 art Exp $ # include <sys/param.h> @@ -49,15 +49,11 @@ include <sys/user.h> # proc fields and values struct proc -member p_forw -member p_back member p_addr member p_stat -member p_wchan member p_cpu member P_ASTPENDING p_md.md_astpending -export SRUN export SONPROC # cpu fields diff --git a/sys/arch/m88k/m88k/m88k_machdep.c b/sys/arch/m88k/m88k/m88k_machdep.c index e9d7b9838ac..76e5329a1c8 100644 --- a/sys/arch/m88k/m88k/m88k_machdep.c +++ b/sys/arch/m88k/m88k/m88k_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m88k_machdep.c,v 1.21 2007/05/29 18:10:42 miod Exp $ */ +/* $OpenBSD: m88k_machdep.c,v 1.22 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -202,50 +202,6 @@ copystr(fromaddr, toaddr, maxlength, lencopied) return (ENAMETOOLONG); } -void -setrunqueue(p) - struct proc *p; -{ - struct prochd *q; - struct proc *oldlast; - int which = p->p_priority >> 2; - -#ifdef DIAGNOSTIC - if (p->p_back != NULL) - panic("setrunqueue %p", p); -#endif - q = &qs[which]; - whichqs |= 1 << which; - p->p_forw = (struct proc *)q; - p->p_back = oldlast = q->ph_rlink; - q->ph_rlink = p; - oldlast->p_forw = p; -} - -/* - * Remove process p from its run queue, which should be the one - * indicated by its priority. Calls should be made at splstatclock(). - */ -void -remrunqueue(vp) - struct proc *vp; -{ - struct proc *p = vp; - int which = p->p_priority >> 2; - struct prochd *q; - -#ifdef DIAGNOSTIC - if ((whichqs & (1 << which)) == 0) - panic("remrq %p", p); -#endif - p->p_forw->p_back = p->p_back; - p->p_back->p_forw = p->p_forw; - p->p_back = NULL; - q = &qs[which]; - if (q->ph_link == (struct proc *)q) - whichqs &= ~(1 << which); -} - #ifdef DDB int longformat = 1; void diff --git a/sys/arch/m88k/m88k/process.S b/sys/arch/m88k/m88k/process.S index 70050662724..786b40d5c38 100644 --- a/sys/arch/m88k/m88k/process.S +++ b/sys/arch/m88k/m88k/process.S @@ -1,4 +1,4 @@ -/* $OpenBSD: process.S,v 1.16 2007/05/12 19:59:52 miod Exp $ */ +/* $OpenBSD: process.S,v 1.17 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1996 Nivas Madhur * All rights reserved. @@ -35,242 +35,63 @@ #include <machine/psl.h> #include <machine/intr.h> -#ifdef DIAGNOSTIC - data - align 4 -ASLOCAL(swchanpanic) - string "switch wchan %x\0" - align 4 -ASLOCAL(swsrunpanic) - string "switch SRUN %x\0" - - text - align 8 -ASLOCAL(Lswchanpanic) - or.u r2, r0, hi16(_ASM_LABEL(swchanpanic)) - or r2, r2, lo16(_ASM_LABEL(swchanpanic)) - bsr.n _C_LABEL(panic) - or r3, r0, r9 - -ASLOCAL(Lswsrunpanic) - or.u r2, r0, hi16(_ASM_LABEL(swsrunpanic)) - or r2, r2, lo16(_ASM_LABEL(swsrunpanic)) - bsr.n _C_LABEL(panic) - or r3, r0, r9 -#endif - /* - * void switch_exit(struct proc *p) + * void cpu_idle_enter() * - * Do the final work to exit from a process. After switching to the - * idle stack and pcb, invoke exit2() on behalf of the exiting process, - * then continue into cpu_switch() to select another process to run. + * Enable all interrupts and lower spl. This actually enables interrupts + * in the psr; bootstrap of secondary processors depends on this. */ - -ENTRY(switch_exit) - /* - * Disable interrupts since we are about to change the kernel - * stack. - */ - ldcr r3, PSR - set r3, r3, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r3, PSR +ENTRY(cpu_idle_enter) + ldcr r2, PSR + clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> + stcr r2, PSR FLUSH_PIPELINE - /* - * Change pcb to idle u. area, i.e., set r31 to top of stack - * and set curpcb to point to the cpu's idle stack. - * r2 contains proc *p. - */ - ldcr r10, CPU - ld r30, r10, CI_IDLE_PCB - addu r31, r30, USIZE /* now on idle stack */ - st r30, r10, CI_CURPCB /* curpcb = idle_pcb */ - - /* Schedule the vmspace and stack to be freed. */ - bsr.n _C_LABEL(exit2) - st r0, r10, CI_CURPROC /* curproc = NULL */ - - /* - * exit2() has acquired the scheduler lock for us. Jump into - * cpu_switch(), after the context save since we do not need - * to save anything. - */ - br _ASM_LABEL(cpu_switch_search) + br.n _C_LABEL(setipl) + or r2, r0, IPL_NONE /* - * void cpu_switch(struct proc *p) + * void cpu_idle_leave() * - * Find a runnable process and switch to it. On entry, the scheduler lock is - * held; it has to be released before returning to the process. + * Raise ipl to IPL_SCHED, but do not attempt to disable interrupts. + */ +ENTRY(cpu_idle_leave) + br.n _C_LABEL(setipl) + or r2, r0, IPL_SCHED + +/* + * void cpu_switchto(struct proc *oldproc, struct proc *newproc) * - * Note that this code ignores its proc parameter and assumes it has the - * same value as curproc. This may change in mi_switch() in the future, - * be careful. + * Switch context from oldproc to newproc. oldproc may be NULL if there is + * no need to save the current context. */ -ENTRY(cpu_switch) +ENTRY(cpu_switchto) /* - * Disable interrupts, we do not want to be disturbed while - * saving context. + * Save state of previous process in its pcb if required. */ - ldcr r2, PSR - set r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r2, PSR - FLUSH_PIPELINE + bcnd eq0, r2, 1f - /* - * Save state of previous process in its pcb, and pmap_deactivate() - * the process. - */ ldcr r2, CPU ld r2, r2, CI_CURPCB st r1, r2, PCB_PC /* save return address */ bsr _ASM_LABEL(__savectx) /* note that we don't need to recover r1 at this point */ +1: ldcr r11, CPU - ld r2, r11, CI_CURPROC - - /* - * Note that we can still use curpcb as our stack after - * pmap_deactivate() has been called, as it does not affect the u - * area mappings. - */ - bsr.n _C_LABEL(pmap_deactivate) - st r0, r11, CI_CURPROC /* curproc = NULL */ - -#ifdef MULTIPROCESSOR - /* - * We need to switch to the processor's idle stack now (in case the - * process we are using the stack of gets scheduled on another - * processor). - */ - ldcr r10, CPU - ld r30, r10, CI_IDLE_PCB - addu r31, r30, USIZE /* now on idle stack */ - st r30, r10, CI_CURPCB /* curpcb = idle_pcb */ -#endif - -ASLOCAL(cpu_switch_search) - /* - * This is the start of the idle loop. Find the highest-priority - * queue that isn't empty, then take the first proc from that queue. - */ - or.u r7, r0, hi16(_C_LABEL(whichqs)) - ld r7, r7, lo16(_C_LABEL(whichqs)) - bcnd ne0, r7, _ASM_LABEL(cpu_switch_found) - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bsr _C_LABEL(sched_unlock_idle) -#endif - -#ifdef MULTIPROCESSOR -ASGLOBAL(cpu_switch_idle) -#else -ASLOCAL(cpu_switch_idle) -#endif - /* - * There were no runnable processes. Enable all interrupts and - * busy-wait for this to change. - * Note that, besides doing setipl(IPL_NONE), this will actually enable - * interrupts in the psr. Bootstrap of secondary processors - * relies upon this. - */ - ldcr r2, PSR - clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r2, PSR - FLUSH_PIPELINE - - bsr.n _C_LABEL(setipl) - or r2, r0, IPL_NONE - - or.u r7, r0, hi16(_C_LABEL(whichqs)) - ld r7, r7, lo16(_C_LABEL(whichqs)) - bcnd eq0, r7, _ASM_LABEL(cpu_switch_idle) - /* XXX run fancy things here, such as page zeroing... */ - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bsr _C_LABEL(sched_lock_idle) -#endif - -ASLOCAL(cpu_switch_found) - /* - * Disable interrupts. - */ - ldcr r2, PSR - set r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r2, PSR - FLUSH_PIPELINE - - /* - * An interrupt could have occured between the last whichqs check - * and the call to setipl(). Check again that whichqs is nonzero. - */ - or.u r7, r0, hi16(_C_LABEL(whichqs)) /* reload whichqs */ - ld r7, r7, lo16(_C_LABEL(whichqs)) - bcnd eq0, r7, _ASM_LABEL(cpu_switch_search) - - /* XXX use ff1, like powerpc... needs *runqueue() adjustments */ - xor r6, r6, r6 /* set r6 to 0 */ -1: bb1 0, r7, 2f /* if rightmost bit set, done */ - extu r7, r7, 0<1> /* else, right shift whichqs, */ - br.n 1b /* increment r6, and repeat */ - addu r6, r6, 1 -2: - or.u r7, r0, hi16(_C_LABEL(qs)) - or r7, r7, lo16(_C_LABEL(qs)) - - /* - * Need to make - * p->p_forw->p_back = p->p_back and - * p->p_back->p_forw = p->p_forw where - * p is q->p_forw. - * Remember that q->p_forw == p and p->p_back == q. - */ - - lda.d r8, r7[r6] /* r8 = &qs[ff1(whichqs)] */ - ld r9, r8, P_FORW /* r8 is q, r9 is p */ - - ld r12, r9, P_FORW /* r12 = p->p_forw */ - st r8, r12, P_BACK /* p->p_forw->p_back = q (p->p_back) */ - st r12, r8, P_FORW /* q->p_forw = p->p_forw */ - lda.d r8, r7[r6] /* reload r8 with qs[ff1(whichqs)] */ - ld r12, r8, P_FORW /* q->p_forw */ - cmp r12, r12, r8 /* q == q->p_forw; anyone left on queue? */ - bb1 ne, r12, 3f /* yes, skip clearing bit in whichqs */ - - or r12, r0, 1 - mak r12, r12, r6 - or.u r7, r0, hi16(_C_LABEL(whichqs)) - ld r8, r7, lo16(_C_LABEL(whichqs)) - and.c r8, r8, r12 /* whichqs &= ~the bit */ - st r8, r7, lo16(_C_LABEL(whichqs)) -3: -#ifdef DIAGNOSTIC - ld r2, r9, P_WCHAN - bcnd ne0, r2, _ASM_LABEL(Lswchanpanic) - ld.b r2, r9, P_STAT - cmp r2, r2, SRUN - bb1 ne, r2, _ASM_LABEL(Lswsrunpanic) -#endif - - ldcr r11, CPU - st r0, r11, CI_WANT_RESCHED /* clear want_resched */ + st r3, r11, CI_CURPROC /* curproc = newproc */ - st r9, r11, CI_CURPROC /* curproc = p */ or r2, r0, SONPROC - st.b r2, r9, P_STAT + st.b r2, r3, P_STAT #ifdef MULTIPROCESSOR - st r11, r9, P_CPU /* p->p_cpu = curcpu */ + st r11, r3, P_CPU /* p->p_cpu = curcpu */ #endif - - ld r3, r9, P_ADDR - st r0, r9, P_BACK /* p->p_back = 0 */ - st r3, r11, CI_CURPCB /* curpcb = p->p_addr */ + ld r2, r3, P_ADDR + st r2, r11, CI_CURPCB /* curpcb = p->p_addr */ /* pmap_activate() the process' pmap */ bsr.n _C_LABEL(pmap_activate) - or r2, r0, r9 + or r2, r0, r3 ldcr r10, CPU ld r10, r10, CI_CURPCB @@ -297,25 +118,9 @@ ASLOCAL(cpu_switch_found) ld r29, r10, PCB_R29 ld r30, r10, PCB_R30 /* restore frame pointer & stack */ ld r31, r10, PCB_SP -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bsr.n _C_LABEL(sched_unlock_idle) - or r14, r10, r0 - ld r1, r14, PCB_PC - ld r14, r14, PCB_R14 -#else ld r1, r10, PCB_PC - ld r14, r10, PCB_R14 -#endif - - /* - * Enable interrupts again. - */ - ldcr r2, PSR - clr r2, r2, 1<PSR_INTERRUPT_DISABLE_BIT> - stcr r2, PSR - FLUSH_PIPELINE - - jmp r1 + jmp.n r1 + ld r14, r10, PCB_R14 /* * savectx(pcb) diff --git a/sys/arch/m88k/m88k/vm_machdep.c b/sys/arch/m88k/m88k/vm_machdep.c index f6283b85b56..e967b892cf8 100644 --- a/sys/arch/m88k/m88k/vm_machdep.c +++ b/sys/arch/m88k/m88k/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.15 2007/06/20 17:29:36 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.16 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. @@ -136,20 +136,17 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) /* * cpu_exit is called as the last action during exit. - * We release the address space and machine-dependent resources, - * including the memory for the user structure and kernel stack. - * Once finished, we call switch_exit, which switches to a temporary - * pcb and stack and never returns. We block memory allocation - * until switch_exit has made things safe again. + * + * Block context switches and then call switch_exit() which will + * switch to another process thus we never return. */ void cpu_exit(struct proc *p) { - splhigh(); + (void)splhigh(); pmap_deactivate(p); - switch_exit(p); - /* NOTREACHED */ + sched_exit(p); } /* diff --git a/sys/arch/mac68k/mac68k/locore.s b/sys/arch/mac68k/mac68k/locore.s index 16809cabe7d..1c589abad89 100644 --- a/sys/arch/mac68k/mac68k/locore.s +++ b/sys/arch/mac68k/mac68k/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.58 2007/05/15 13:46:22 martin Exp $ */ +/* $OpenBSD: locore.s,v 1.59 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: locore.s,v 1.103 1998/07/09 06:02:50 scottr Exp $ */ /* @@ -954,52 +954,18 @@ Ldorte: */ #include <m68k/m68k/support.s> -/* - * Use common m68k process manipulation routines. - */ -#include <m68k/m68k/proc_subr.s> - .data GLOBAL(curpcb) .long 0 ASBSS(nullpcb,SIZEOF_PCB) -/* - * At exit of a process, do a switch for the last time. - * Switch to a safe stack and PCB, and select a new process to run. The - * old stack and u-area will be freed by the reaper. - */ -ENTRY(switch_exit) - movl sp@(4),a0 - /* save state into garbage pcb */ - movl #_ASM_LABEL(nullpcb),_C_LABEL(curpcb) - lea _ASM_LABEL(tmpstk),sp | goto a tmp stack - - /* Schedule the vmspace and stack to be freed. */ - movl a0,sp@- | exit2(p) - jbsr _C_LABEL(exit2) - lea sp@(4),sp | pop args - - jra _C_LABEL(cpu_switch) - -/* - * When no processes are on the runq, Swtch branches to Idle - * to wait for something to come ready. - */ -ASENTRY_NOPROFILE(Idle) +ENTRY_NOPROFILE(cpu_idle_cycle) stop #PSL_LOWIPL - movw #PSL_HIGHIPL,sr - movl _C_LABEL(whichqs),d0 - jeq _ASM_LABEL(Idle) - jra Lsw1 - -Lbadsw: - PANIC("switch") - /*NOTREACHED*/ + rts /* - * cpu_switch() + * cpu_switchto(struct proc *oldproc, struct proc *newproc) * * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the * entire ATC. The effort involved in selective flushing may not be @@ -1009,55 +975,15 @@ Lbadsw: * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag * bit). For now, we just always flush the full ATC. */ -ENTRY(cpu_switch) - movl _C_LABEL(curpcb),a0 | current pcb - movw sr,a0@(PCB_PS) | save sr before changing ipl -#ifdef notyet - movl CURPROC,sp@- | remember last proc running -#endif - clrl CURPROC +ENTRY(cpu_switchto) + movl sp@(4), d0 | oldproc + beq Lswnofpsave | is NULL, don't save anything /* - * Find the highest-priority queue that isn't empty, - * then take the first proc from that queue. - */ - movw #PSL_HIGHIPL,sr | lock out interrupts - movl _C_LABEL(whichqs),d0 - jeq _ASM_LABEL(Idle) -Lsw1: - movl d0,d1 - negl d0 - andl d1,d0 - bfffo d0{#0:#32},d1 - eorib #31,d1 - - movl d1,d0 - lslb #3,d1 | convert queue number to index - addl #_C_LABEL(qs),d1 | locate queue (q) - movl d1,a1 - movl a1@(P_FORW),a0 | p = q->p_forw - cmpal d1,a0 | anyone on queue? - jeq Lbadsw | no, panic - movl a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw - movl a0@(P_FORW),a1 | n = p->p_forw - movl d1,a1@(P_BACK) | n->p_back = q - cmpal d1,a1 | anyone left on queue? - jne Lsw2 | yes, skip - movl _C_LABEL(whichqs),d1 - bclr d0,d1 | no, clear bit - movl d1,_C_LABEL(whichqs) -Lsw2: - movl a0,CURPROC - clrl _C_LABEL(want_resched) -#ifdef notyet - movl sp@+,a1 - cmpl a0,a1 | switching to same proc? - jeq Lswdone | yes, skip save and restore -#endif - /* * Save state of previous process in its pcb. */ movl _C_LABEL(curpcb),a1 + movw sr, a1@(PCB_PS) | save sr before switching context moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers movl usp,a2 | grab USP (a2 has been saved) movl a2,a1@(PCB_USP) | and save it @@ -1070,16 +996,12 @@ Lsw2: jeq Lswnofpsave | yes, all done fmovem fp0-fp7,a2@(FPF_REGS) | save FP general registers fmovem fpcr/fpsr/fpi,a2@(FPF_FPCR) | save FP control registers + Lswnofpsave: + movl sp@(8), a0 | newproc -#ifdef DIAGNOSTIC - tstl a0@(P_WCHAN) - jne Lbadsw - cmpb #SRUN,a0@(P_STAT) - jne Lbadsw -#endif + movl a0, CURPROC movb #SONPROC,a0@(P_STAT) - clrl a0@(P_BACK) | clear back link movl a0@(P_ADDR),a1 | get p_addr movl a1,_C_LABEL(curpcb) diff --git a/sys/arch/mac68k/mac68k/vm_machdep.c b/sys/arch/mac68k/mac68k/vm_machdep.c index 00bb0bce0d7..6ff6156056b 100644 --- a/sys/arch/mac68k/mac68k/vm_machdep.c +++ b/sys/arch/mac68k/mac68k/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.39 2007/05/27 20:59:25 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.40 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.29 1998/07/28 18:34:55 thorpej Exp $ */ /* @@ -119,19 +119,18 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) /* * cpu_exit is called as the last action during exit. - * We release the address space and machine-dependent resources, - * block context switches and then call switch_exit() which will - * free our stack and user area and switch to another process. - * Thus, we never return. + * + * Block context switches and then call switch_exit() which will + * switch to another process thus we never return. */ void cpu_exit(p) struct proc *p; { - (void)splhigh(); - switch_exit(p); - /* NOTREACHED */ + + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/macppc/macppc/cpu.c b/sys/arch/macppc/macppc/cpu.c index 9838e1d9c9c..c3ca93afd75 100644 --- a/sys/arch/macppc/macppc/cpu.c +++ b/sys/arch/macppc/macppc/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.43 2007/05/23 23:40:21 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.44 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1997 Per Fogelstrom @@ -676,7 +676,7 @@ void cpu_hatch(void) { volatile struct cpu_hatch_data *h = cpu_hatch_data; - int scratch, i; + int scratch, i, s; /* Initialize timebase. */ __asm ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0)); @@ -759,5 +759,12 @@ cpu_hatch(void) curcpu()->ci_ipending = 0; curcpu()->ci_cpl = 0; + + s = splhigh(); + microuptime(&curcpu()->ci_schedstate.spc_runtime); + splx(s); + + SCHED_LOCK(s); + cpu_switchto(NULL, sched_chooseproc()); } #endif diff --git a/sys/arch/macppc/macppc/genassym.cf b/sys/arch/macppc/macppc/genassym.cf index 4249820a8c6..2efd74a41b6 100644 --- a/sys/arch/macppc/macppc/genassym.cf +++ b/sys/arch/macppc/macppc/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.14 2007/03/22 19:26:28 kettenis Exp $ +# $OpenBSD: genassym.cf,v 1.15 2007/10/10 15:53:52 art Exp $ # # Copyright (c) 1982, 1990 The Regents of the University of California. # All rights reserved. @@ -61,7 +61,6 @@ define SFRAMELEN roundup(sizeof(struct switchframe), 16) struct pcb member PCB_PMR pcb_pmreal member pcb_sp -member pcb_spl member PCB_FAULT pcb_onfault struct pmap @@ -70,8 +69,6 @@ member PM_USRSR pm_sr[PPC_USER_SR] member PM_KERNELSR pm_sr[PPC_KERNEL_SR] struct proc -member p_forw -member p_back member p_addr member p_stat member p_cpu diff --git a/sys/arch/macppc/macppc/locore.S b/sys/arch/macppc/macppc/locore.S index b2658a7fd48..b840919182d 100644 --- a/sys/arch/macppc/macppc/locore.S +++ b/sys/arch/macppc/macppc/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.32 2007/03/20 20:59:54 kettenis Exp $ */ +/* $OpenBSD: locore.S,v 1.33 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $ */ /* @@ -133,150 +133,41 @@ _ENTRY(_C_LABEL(cpu_spinup_trampoline)) lis %r3,_C_LABEL(cpu_hatch_stack)@ha lwz %r1,_C_LABEL(cpu_hatch_stack)@l(%r3) - bl _C_LABEL(cpu_hatch) - bl _C_LABEL(sched_lock_idle) - li %r30,0 - b _C_LABEL(idle) + b _C_LABEL(cpu_hatch) + /* NOTREACHED */ #endif -/* - * No processes are runnable, so loop waiting for one. - * Separate label here for accounting purposes. - */ - .globl _C_LABEL(idle) - .type _C_LABEL(idle),@function -_C_LABEL(idle): - mfmsr %r3 - /* disable interrupts while manipulating runque */ - andi. %r3,%r3,~PSL_EE@l - mtmsr %r3 - - lis %r8,_C_LABEL(whichqs)@ha - lwz %r9,_C_LABEL(whichqs)@l(%r8) - - or. %r9,%r9,%r9 - bne- _C_LABEL(sw1) /* at least one queue non-empty */ - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bl _C_LABEL(sched_unlock_idle) -#endif - - ori %r3,%r3,PSL_EE /* reenable ints again */ - mtmsr %r3 - isync - sync - /* low power mode */ - mfmsr %r3 - oris %r3, %r3, PSL_POW@h - mtmsr %r3 - isync - -/* May do some power saving here? */ - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bl _C_LABEL(sched_lock_idle) -#endif - b _C_LABEL(idle) - -/* - * switchexit gets called from cpu_exit to free the user structure - * and kernel stack of the current process. - */ -_ENTRY(_C_LABEL(switchexit)) -/* First switch to the idle pcb/kernel stack */ - GET_CPUINFO(%r7) - lwz %r6,CI_IDLE_PCB(%r7) - stw %r6,CI_CURPCB(%r7) - addi %r1,%r6,USPACE-16 /* 16 bytes are reserved at stack top */ - /* - * Schedule the vmspace and stack to be freed (the proc arg is - * already in r3). - */ - bl _C_LABEL(exit2) - - /* Fall through to cpu_switch to actually select another proc */ - li %r3,0 /* indicate exited process */ - -/* Fall through to cpu_switch to actually select another proc */ /* - * void cpu_switch(struct proc *p) - * Find a runnable process and switch to it. + * void cpu_switchto(struct proc *old, struct proc *new) + * Switch from "old" proc to "new". */ -_ENTRY(_C_LABEL(cpu_switch)) +_ENTRY(_C_LABEL(cpu_switchto)) mflr %r0 /* save lr */ stw %r0,4(%r1) stwu %r1,-16(%r1) stw %r31,12(%r1) stw %r30,8(%r1) - mr %r30,%r3 - GET_CPUINFO(%r3) +/* + * r3 - old proc + * r4 - new proc + * r5 - cpuinfo + */ + GET_CPUINFO(%r5) li %r31,0 - /* Zero to not accumulate cpu time */ - stw %r31,CI_CURPROC(%r3) - lwz %r31,CI_CURPCB(%r3) - - li %r3,0 - bl _C_LABEL(lcsplx) - stw %r3,PCB_SPL(%r31) /* save spl */ - -/* Find a new process */ - mfmsr %r3 - andi. %r3,%r3,~PSL_EE@l /* disable interrupts while - manipulating runque */ - mtmsr %r3 - isync - - lis %r8,_C_LABEL(whichqs)@ha - lwz %r9,_C_LABEL(whichqs)@l(%r8) - - or. %r9,%r9,%r9 - beq- _C_LABEL(idle) /* all queues empty */ -_C_LABEL(sw1): - cntlzw %r10,%r9 - lis %r4,_C_LABEL(qs)@ha - addi %r4,%r4,_C_LABEL(qs)@l - slwi %r3,%r10,3 - add %r3,%r3,%r4 /* select queue */ - - lwz %r31,P_FORW(%r3) /* unlink first proc from queue */ - lwz %r4,P_FORW(%r31) - stw %r4,P_FORW(%r3) - stw %r3,P_BACK(%r4) - - cmpl 0,%r3,%r4 /* queue empty? */ - bne 1f - - lis %r3,0x80000000@ha - srw %r3,%r3,%r10 - andc %r9,%r9,%r3 - stw %r9,_C_LABEL(whichqs)@l(%r8) /* mark it empty */ - -1: /* just did this resched thing, clear resched */ - li %r3,0 - GET_CPUINFO(%r4) - stw %r3,CI_WANT_RESCHED(%r4) - - stw %r3,P_BACK(%r31) /* probably superfluous */ + stw %r31,CI_WANT_RESCHED(%r5) #ifdef MULTIPROCESSOR - stw %r4,P_CPU(%r31) + stw %r5,P_CPU(%r4) #endif - stw %r31,CI_CURPROC(%r4) /* record new process */ - - li %r3,SONPROC - stb %r3,P_STAT(%r31) - - mfmsr %r3 - ori %r3,%r3,PSL_EE /* Now we can interrupt again */ - mtmsr %r3 + stw %r4,CI_CURPROC(%r5) /* record new process */ - cmpl 0,%r31,%r30 /* is it the same process? */ - beq switch_return + li %r31,SONPROC + stb %r31,P_STAT(%r4) - or. %r30,%r30,%r30 /* old process was exiting? */ + or. %r3,%r3,%r3 /* old process was exiting? */ beq switch_exited mfsr %r10,PPC_USER_SR /* save PPC_USER_SR for copyin/copyout*/ @@ -284,33 +175,31 @@ _C_LABEL(sw1): mr %r12,%r2 /* save r2 */ stwu %r1,-SFRAMELEN(%r1) /* still running on old stack */ stmw %r10,8(%r1) - lwz %r3,P_ADDR(%r30) - stw %r1,PCB_SP(%r3) /* save SP */ + lwz %r31,P_ADDR(%r3) + stw %r1,PCB_SP(%r31) /* save SP */ switch_exited: /* disable interrupts while actually switching */ - mfmsr %r3 - andi. %r3,%r3,~PSL_EE@l - mtmsr %r3 + mfmsr %r30 + andi. %r30,%r30,~PSL_EE@l + mtmsr %r30 - lwz %r4,P_ADDR(%r31) - GET_CPUINFO(%r5) - stw %r4,CI_CURPCB(%r5) /* indicate new pcb */ + lwz %r31,P_ADDR(%r4) + stw %r31,CI_CURPCB(%r5) /* indicate new pcb */ - lwz %r5,PCB_PMR(%r4) + lwz %r6,PCB_PMR(%r31) /* save real pmap pointer for spill fill */ - GET_CPUINFO(%r6) - stwu %r5,CI_CURPM(%r6) - stwcx. %r5,%r0,%r6 /* clear possible reservation */ + stwu %r6,CI_CURPM(%r5) + stwcx. %r6,%r0,%r5 /* clear possible reservation */ - addic. %r5,%r5,64 - li %r6,0 + addic. %r6,%r6,64 + li %r5,0 - lwz %r1,PCB_SP(%r4) /* get new procs SP */ + lwz %r1,PCB_SP(%r31) /* get new procs SP */ - ori %r3,%r3,PSL_EE /* interrupts are okay again */ - mtmsr %r3 + ori %r30,%r30,PSL_EE /* interrupts are okay again */ + mtmsr %r30 lmw %r10,8(%r1) /* get other regs */ lwz %r1,0(%r1) /* get saved SP */ @@ -320,17 +209,6 @@ switch_exited: mtsr PPC_USER_SR,%r10 /* get saved PPC_USER_SR */ isync -switch_return: - mr %r30,%r7 /* save proc pointer */ - lwz %r3,PCB_SPL(%r4) - bl _C_LABEL(lcsplx) - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - bl _C_LABEL(sched_unlock_idle) -#endif - - mr %r3,%r30 /* curproc for special fork returns */ - lwz %r31,12(%r1) lwz %r30,8(%r1) addi %r1,%r1,16 @@ -338,6 +216,19 @@ switch_return: mtlr %r0 blr +_ENTRY(_C_LABEL(cpu_idle_enter)) + blr + +_ENTRY(_C_LABEL(cpu_idle_cycle)) + /* low power mode */ + mfmsr %r3 + oris %r3, %r3, PSL_POW@h + mtmsr %r3 + isync + blr + +_ENTRY(_C_LABEL(cpu_idle_leave)) + blr /* * Data used during primary/secondary traps/interrupts diff --git a/sys/arch/mips64/mips64/context.S b/sys/arch/mips64/mips64/context.S index 79f9869a438..24deaf3b2ec 100644 --- a/sys/arch/mips64/mips64/context.S +++ b/sys/arch/mips64/mips64/context.S @@ -1,4 +1,4 @@ -/* $OpenBSD: context.S,v 1.13 2007/07/16 20:22:18 miod Exp $ */ +/* $OpenBSD: context.S,v 1.14 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -69,92 +69,11 @@ LEAF(savectx, 0) move v0, zero END(savectx) -/* - * The following primitives manipulate the run queues. _whichqs tells which - * of the 32 queues _qs have processes in them. Setrunqueue puts processes - * into queues, Remrq removes them from queues. The running process is on - * no queue, other processes are on a queue related to p->p_priority, divided - * by 4 actually to shrink the 0-127 range of priorities into the 32 available - * queues. - */ -/* - * setrunqueue(p) - * proc *p; - * - * Call should be made at splclock(), and p->p_stat should be SRUN. - */ -NON_LEAF(setrunqueue, FRAMESZ(CF_SZ), ra) - .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) - PTR_L t0, P_BACK(a0) ## firewall: p->p_back must be 0 - bne t0, zero, 1f ## - lbu t0, P_PRIORITY(a0) # put on p->p_priority / 4 queue - li t1, 1 # compute corresponding bit - srl t0, t0, 2 # compute index into 'whichqs' - sll t1, t1, t0 - lw t2, whichqs # set corresponding bit - sll t0, t0, LOGREGSZ+1 # compute index into 'qs' - or t2, t2, t1 - sw t2, whichqs - LA t1, qs - PTR_ADDU t0, t0, t1 # t0 = qp = &qs[pri >> 2] - PTR_L t1, P_BACK(t0) # t1 = qp->ph_rlink - PTR_S t0, P_FORW(a0) # p->p_forw = qp - PTR_S t1, P_BACK(a0) # p->p_back = qp->ph_rlink - PTR_S a0, P_FORW(t1) # p->p_back->p_forw = p; - j ra - PTR_S a0, P_BACK(t0) # qp->ph_rlink = p - -1: +NON_LEAF(cpu_idle_enter, FRAMESZ(CF_SZ), ra) PTR_SUBU sp, sp, FRAMESZ(CF_SZ) PTR_S ra, CF_RA_OFFS(sp) - PANIC("setrunqueue") - jr ra - nop -END(setrunqueue) - -/* - * Remrq(p) - * - * Call should be made at splclock(). - */ -NON_LEAF(remrunqueue, FRAMESZ(CF_SZ), ra) .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) - lbu t0, P_PRIORITY(a0) # get from p->p_priority / 4 queue - li t1, 1 # compute corresponding bit - srl t0, t0, 2 # compute index into 'whichqs' - lw t2, whichqs # check corresponding bit - sll t1, t1, t0 - and v0, t2, t1 - beqz v0, 2f # oops! queue is empty! - PTR_L v0, P_BACK(a0) # v0 = p->p_back - - PTR_L v1, P_FORW(a0) # v1 = p->p_forw - PTR_SLL t0, t0, LOGREGSZ+1 # compute index into 'qs' - PTR_S v1, P_FORW(v0) # p->p_back->p_forw = p->p_forw; - PTR_S v0, P_BACK(v1) # p->p_forw->p_back = p->r_rlink - LA v0, qs - PTR_ADDU t0, t0, v0 # t0 = qp = &qs[pri >> 2] - PTR_L v0, P_FORW(t0) # check if queue empty - bne v0, t0, 1f # No. qp->ph_link != qp - xor t2, t2, t1 # clear corresponding bit in 'whichqs' - sw t2, whichqs -1: - j ra - PTR_S zero, P_BACK(a0) # for firewall checking -2: - PTR_SUBU sp, sp, FRAMESZ(CF_SZ) - PTR_S ra, CF_RA_OFFS(sp) - PANIC("remrunqueue empty") - jr ra - nop -END(remrunqueue) - -/* - * Idle, this is where we spend time when nothing to do. - */ -LEAF(idle, 0) -_idle: sw zero, cpl # lower to spl0 lw t0, ipending beqz t0, 1f @@ -175,63 +94,57 @@ _idle: jal updateimask # Make sure SR imask is updated xor a0, a0 - li t1,1 #if defined(TGT_CP7000) || defined(TGT_CP7000G) PTR_L t2, misc_h # if non zero, do Ocelot LEDs. beqz t2, 1f li t0, 0x40 sb t0, 0x0d(t2) -#endif 1: - lw t0, whichqs # look for non-empty queue - beq t0, zero, 1b - nop +#endif + + PTR_L ra, CF_RA_OFFS(sp) + j ra + PTR_ADDU sp, sp, FRAMESZ(CF_SZ) +END(cpu_idle_enter) + +LEAF(cpu_idle_leave, 0) #if defined(TGT_CP7000) || defined(TGT_CP7000G) - beqz t2, sw1 + PTR_L t2, misc_h # if non zero, do Ocelot LEDs. + beqz t2, 1f li t0, 0x40 sb t0, 0x0c(t2) +1: #endif - b sw1 # Hey, time to do some work! - nop - jr ra # DDB trace - nop - .globl e_idle -e_idle: -END(idle) -/* - * switch_exit(p) - * - * At exit of a process, do a cpu_switch for the last time. - * All interrupts should be blocked at this point. - */ -LEAF(switch_exit, 0) - mfc0 v0, COP_0_STATUS_REG - li v1, ~SR_INT_ENAB - and v0, v0, v1 - mtc0 v0, COP_0_STATUS_REG + mfc0 a0, COP_0_STATUS_REG # disable interrupts + li a1, ~SR_INT_ENAB + and a0, a0, a1 + mtc0 a0, COP_0_STATUS_REG ITLBNOPFIX - LA sp, idle_stack - FRAMESZ(CF_SZ) - jal exit2 - nop - PTR_S zero, curproc - b sw0 + j ra nop - jr ra # DDB trace +END(cpu_idle_leave) + +LEAF(cpu_idle_cycle, 0) + j ra nop -END(switch_exit) +END(cpu_idle_cycle) /* - * cpu_switch() - * Find the highest priority process and resume it. + * cpu_switchto(struct proc *oldproc, struct proc *newproc) */ -NON_LEAF(cpu_switch, FRAMESZ(CF_SZ), ra) +NON_LEAF(cpu_switchto, FRAMESZ(CF_SZ), ra) PTR_L t3, curprocpaddr REG_S sp, PCB_CONTEXT+8*REGSZ(t3) # save old sp + PTR_SUBU sp, sp, FRAMESZ(CF_SZ) REG_S ra, CF_RA_OFFS(sp) .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ)) + + beqz a0, 1f + nop + lw t0, cpl REG_S t0, PCB_CONTEXT+13*REGSZ(t3) REG_S s0, PCB_CONTEXT+0*REGSZ(t3) # do a 'savectx()' @@ -249,59 +162,23 @@ NON_LEAF(cpu_switch, FRAMESZ(CF_SZ), ra) REG_S t0, PCB_CONTEXT+11*REGSZ(t3) REG_S t1, PCB_CONTEXT+12*REGSZ(t3) -sw0: -# lw t2, cnt+V_SWTCH # for statistics - lw t1, whichqs # look for non-empty queue -# addu t2, t2, 1 -# sw t2, cnt+V_SWTCH - beq t1, zero, _idle # if none, idle - nop -sw1: - mfc0 v0, COP_0_STATUS_REG +1: + /* + * Disable interrupts + */ + mfc0 v0, COP_0_STATUS_REG # disable interrupts li v1, ~SR_INT_ENAB and v0, v0, v1 mtc0 v0, COP_0_STATUS_REG ITLBNOPFIX - lw t0, whichqs # look for non-empty queue - li t2, -1 # t2 = lowest bit set - beq t0, zero, _idle # if none, idle - move t3, t0 # t3 = saved whichqs -1: - addu t2, t2, 1 - and t1, t0, 1 # bit set? - beq t1, zero, 1b - srl t0, t0, 1 # try next bit -/* - * Remove process from queue. - */ - PTR_SLL t0, t2, LOGREGSZ+1 - LA t1, qs - PTR_ADDU t0, t0, t1 # t0 = qp = &qs[highbit] - PTR_L a0, P_FORW(t0) # a0 = p = highest pri process - PTR_L v0, P_FORW(a0) # v0 = p->p_forw - beq t0, a0, 4f # make sure something in queue - PTR_S v0, P_FORW(t0) # qp->ph_link = p->p_forw; - PTR_S t0, P_BACK(v0) # p->p_forw->p_back = qp - bne v0, t0, 2f # queue still not empty - PTR_S zero, P_BACK(a0) ## for firewall checking - li v1, 1 # compute bit in 'whichqs' - sll v1, v1, t2 - xor t3, t3, v1 # clear bit in 'whichqs' - sw t3, whichqs -2: -/* - * Switch to new context. - */ - sw zero, want_resched - jal pmap_activate # v0 = TLB PID - move s0, a0 # BDSLOT: save p -/* - * We need to wire the process kernel stack mapping so there - * will be no tlb misses in exception handlers. This is done - * by invalidating any tlb entries mapping the U-area and - * put valid mappings in tlb entries 0 and 1. - */ + /* + * Switch to new context + */ + move s0, a1 # save p + sw zero, want_resched + jal pmap_activate + move a0, s0 PTR_L t3, P_ADDR(s0) # get uarea pointer. PTR_S s0, curproc # set curproc @@ -310,6 +187,13 @@ sw1: li t1, SONPROC sb t1, P_STAT(s0) # set to onproc. + /* + * We need to wire the process kernel stack mapping so there + * will be no tlb misses in exception handlers. This is done + * by invalidating any tlb entries mapping the U-area and + * put valid mappings in tlb entries 0 and 1. + */ + or v0, t3 dmtc0 v0, COP_0_TLB_HI # init high entry (tlbid) LA t1, (VM_MIN_KERNEL_ADDRESS) @@ -399,9 +283,10 @@ ctx2: ctx3: -/* - * Restore registers and return. - */ + /* + * Restore registers and return. + */ + REG_L a0, PCB_CONTEXT+13*REGSZ(t3) REG_L s0, PCB_CONTEXT+0*REGSZ(t3) REG_L s1, PCB_CONTEXT+1*REGSZ(t3) @@ -428,6 +313,4 @@ ctx3: ITLBNOPFIX j ra nop -4: - PANIC("cpu_switch") # nothing in queue -END(cpu_switch) +END(cpu_switchto) diff --git a/sys/arch/mips64/mips64/db_machdep.c b/sys/arch/mips64/mips64/db_machdep.c index 86f6a435b1a..4e2ee91e71f 100644 --- a/sys/arch/mips64/mips64/db_machdep.c +++ b/sys/arch/mips64/mips64/db_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_machdep.c,v 1.12 2007/09/03 01:15:50 krw Exp $ */ +/* $OpenBSD: db_machdep.c,v 1.13 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se) @@ -221,7 +221,6 @@ db_stack_trace_print(addr, have_addr, count, modif, pr) extern char edata[]; extern char k_intr[]; extern char k_general[]; - extern char idle[]; struct trap_frame *regs = &ddb_regs; /* get initial values from the exception frame */ @@ -396,14 +395,10 @@ loop: } done: - if (symname == NULL) { - if (subr == (long)idle) - (*pr)("idle "); - else - (*pr)("%p ", subr); - } else { + if (symname == NULL) + (*pr)("%p ", subr); + else (*pr)("%s+%p ", symname, diff); - } (*pr)("(%llx,%llx,%llx,%llx) sp %llx ra %llx, sz %d\n", a0, a1, a2, a3, sp, ra, stksize); if (subr == (long)k_intr || subr == (long)k_general) { diff --git a/sys/arch/mips64/mips64/vm_machdep.c b/sys/arch/mips64/mips64/vm_machdep.c index 30f280cc396..d6517d55ffd 100644 --- a/sys/arch/mips64/mips64/vm_machdep.c +++ b/sys/arch/mips64/mips64/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.15 2007/09/03 17:35:51 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.16 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1988 University of Utah. * Copyright (c) 1992, 1993 @@ -134,9 +134,9 @@ cpu_exit(p) if (machFPCurProcPtr == p) machFPCurProcPtr = (struct proc *)0; - (void) splhigh(); - switch_exit(p); - /* NOTREACHED */ + (void)splhigh(); + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/mvme68k/mvme68k/locore.s b/sys/arch/mvme68k/mvme68k/locore.s index 38015370541..c92d4fb2978 100644 --- a/sys/arch/mvme68k/mvme68k/locore.s +++ b/sys/arch/mvme68k/mvme68k/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.54 2007/05/15 13:46:22 martin Exp $ */ +/* $OpenBSD: locore.s,v 1.55 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -1165,51 +1165,18 @@ Ldorte: */ #include <m68k/m68k/support.s> -/* - * Use common m68k process manipulation routines. - */ -#include <m68k/m68k/proc_subr.s> - .data GLOBAL(curpcb) .long 0 ASBSS(nullpcb,SIZEOF_PCB) -/* - * At exit of a process, do a switch for the last time. - * Switch to a safe stack and PCB, and deallocate the process's resources. - */ -ENTRY(switch_exit) - movl sp@(4),a0 - | save state into garbage pcb - movl #_ASM_LABEL(nullpcb),_C_LABEL(curpcb) - lea _ASM_LABEL(tmpstk),sp | goto a tmp stack - - /* Schedule the vmspace and stack to be freed. */ - movl a0,sp@- | exit2(p) - jbsr _C_LABEL(exit2) - lea sp@(4),sp | pop args - - jra _C_LABEL(cpu_switch) - -/* - * When no processes are on the runq, Swtch branches to Idle - * to wait for something to come ready. - */ -ASENTRY_NOPROFILE(Idle) +ENTRY_NOPROFILE(cpu_idle_cycle) stop #PSL_LOWIPL - movw #PSL_HIGHIPL,sr - movl _C_LABEL(whichqs),d0 - jeq _ASM_LABEL(Idle) - jra Lsw1 - -Lbadsw: - PANIC("switch") - /*NOTREACHED*/ + rts /* - * cpu_switch() + * cpu_switchto(struct proc *oldproc, struct proc *newproc) * * NOTE: On the mc68851 we attempt to avoid flushing the * entire ATC. The effort involved in selective flushing may not be @@ -1219,55 +1186,15 @@ Lbadsw: * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag * bit). For now, we just always flush the full ATC. */ -ENTRY(cpu_switch) - movl _C_LABEL(curpcb),a0 | current pcb - movw sr,a0@(PCB_PS) | save sr before changing ipl -#ifdef notyet - movl CURPROC,sp@- | remember last proc running -#endif - clrl CURPROC +ENTRY(cpu_switchto) + movl sp@(4), d0 | oldproc + beq Lswnofpsave | is NULL, don't save anything /* - * Find the highest-priority queue that isn't empty, - * then take the first proc from that queue. - */ - movw #PSL_HIGHIPL,sr | lock out interrupts - movl _C_LABEL(whichqs),d0 - jeq _ASM_LABEL(Idle) -Lsw1: - movl d0,d1 - negl d0 - andl d1,d0 - bfffo d0{#0:#32},d1 - eorib #31,d1 - - movl d1,d0 - lslb #3,d1 | convert queue number to index - addl #_C_LABEL(qs),d1 | locate queue (q) - movl d1,a1 - movl a1@(P_FORW),a0 | p = q->p_forw - cmpal d1,a0 | anyone on queue? - jeq Lbadsw | no, panic - movl a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw - movl a0@(P_FORW),a1 | n = p->p_forw - movl d1,a1@(P_BACK) | n->p_back = q - cmpal d1,a1 | anyone left on queue? - jne Lsw2 | yes, skip - movl _C_LABEL(whichqs),d1 - bclr d0,d1 | no, clear bit - movl d1,_C_LABEL(whichqs) -Lsw2: - movl a0,CURPROC - clrl _C_LABEL(want_resched) -#ifdef notyet - movl sp@+,a1 - cmpl a0,a1 | switching to same proc? - jeq Lswdone | yes, skip save and restore -#endif - /* * Save state of previous process in its pcb. */ movl _C_LABEL(curpcb),a1 + movw sr, a1@(PCB_PS) | save sr before switching context moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers movl usp,a2 | grab USP (a2 has been saved) movl a2,a1@(PCB_USP) | and save it @@ -1295,15 +1222,12 @@ Lsavfp60: fmovem fpsr,a2@(FPF_FPSR) fmovem fpi,a2@(FPF_FPI) #endif /* M68060 */ + Lswnofpsave: -#ifdef DIAGNOSTIC - tstl a0@(P_WCHAN) - jne Lbadsw - cmpb #SRUN,a0@(P_STAT) - jne Lbadsw -#endif + movl sp@(8), a0 | newproc + + movl a0, CURPROC movb #SONPROC,a0@(P_STAT) - clrl a0@(P_BACK) | clear back link movl a0@(P_ADDR),a1 | get p_addr movl a1,_C_LABEL(curpcb) diff --git a/sys/arch/mvme68k/mvme68k/vm_machdep.c b/sys/arch/mvme68k/mvme68k/vm_machdep.c index e8ac2262a05..df44535cfda 100644 --- a/sys/arch/mvme68k/mvme68k/vm_machdep.c +++ b/sys/arch/mvme68k/mvme68k/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.45 2007/06/20 17:29:36 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.46 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -117,20 +117,18 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) /* * cpu_exit is called as the last action during exit. - * We release the address space and machine-dependent resources, - * including the memory for the user structure and kernel stack. - * Once finished, we call switch_exit, which switches to a temporary - * pcb and stack and never returns. We block memory allocation - * until switch_exit has made things safe again. + * + * Block context switches and then call switch_exit() which will + * switch to another process thus we never return. */ void cpu_exit(p) struct proc *p; { + (void)splhigh(); - splhigh(); - switch_exit(p); - /* NOTREACHED */ + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/mvme88k/mvme88k/locore.S b/sys/arch/mvme88k/mvme88k/locore.S index 980804454bc..355d0dae81a 100644 --- a/sys/arch/mvme88k/mvme88k/locore.S +++ b/sys/arch/mvme88k/mvme88k/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.49 2006/05/08 14:03:35 miod Exp $ */ +/* $OpenBSD: locore.S,v 1.50 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 2005, Miodrag Vallat. * Copyright (c) 1998 Steve Murphree, Jr. @@ -346,14 +346,6 @@ GLOBAL(secondary_start) bsr.n _C_LABEL(secondary_main) addu r31, r3, USIZE /* switch to idle stack */ - /* - * At this point, the CPU has been correctly initialized and has - * identified itself on the console. - * All it needs now is to jump to the idle loop and wait for work to - * be offered. - */ - br _ASM_LABEL(cpu_switch_idle) - #endif /* MULTIPROCESSOR */ /* diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index c743056aafa..6c94e8288aa 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.192 2007/06/06 17:15:12 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.193 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -719,19 +719,18 @@ void secondary_main() { struct cpu_info *ci = curcpu(); + int s; cpu_configuration_print(0); + sched_init_cpu(ci); ncpus++; __cpu_simple_unlock(&cpu_mutex); microuptime(&ci->ci_schedstate.spc_runtime); ci->ci_curproc = NULL; - /* - * Upon return, the secondary cpu bootstrap code in locore will - * enter the idle loop, waiting for some food to process on this - * processor. - */ + SCHED_LOCK(s); + cpu_switchto(NULL, sched_chooseproc()); } #endif /* MULTIPROCESSOR */ diff --git a/sys/arch/powerpc/conf/files.powerpc b/sys/arch/powerpc/conf/files.powerpc index 9bfb6960e27..d3effdc83a4 100644 --- a/sys/arch/powerpc/conf/files.powerpc +++ b/sys/arch/powerpc/conf/files.powerpc @@ -1,8 +1,7 @@ -# $OpenBSD: files.powerpc,v 1.42 2007/03/22 19:26:27 kettenis Exp $ +# $OpenBSD: files.powerpc,v 1.43 2007/10/10 15:53:52 art Exp $ # file arch/powerpc/powerpc/setjmp.S ddb -file arch/powerpc/powerpc/Locore.c file arch/powerpc/powerpc/bcopy.c file arch/powerpc/powerpc/copystr.c file arch/powerpc/powerpc/cpu_subr.c diff --git a/sys/arch/powerpc/include/pcb.h b/sys/arch/powerpc/include/pcb.h index a49d03f1488..7560dee7b17 100644 --- a/sys/arch/powerpc/include/pcb.h +++ b/sys/arch/powerpc/include/pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcb.h,v 1.10 2007/03/20 20:59:53 kettenis Exp $ */ +/* $OpenBSD: pcb.h,v 1.11 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: pcb.h,v 1.1 1996/09/30 16:34:29 ws Exp $ */ /*- @@ -49,7 +49,6 @@ struct pcb { struct pmap *pcb_pm; /* pmap of our vmspace */ struct pmap *pcb_pmreal; /* real address of above */ register_t pcb_sp; /* saved SP */ - int pcb_spl; /* saved SPL */ faultbuf *pcb_onfault; /* For use during copyin/copyout */ int pcb_flags; #define PCB_FPU 1 /* Process had FPU initialized */ diff --git a/sys/arch/powerpc/powerpc/vm_machdep.c b/sys/arch/powerpc/powerpc/vm_machdep.c index 5a7d92622de..89755b7c774 100644 --- a/sys/arch/powerpc/powerpc/vm_machdep.c +++ b/sys/arch/powerpc/powerpc/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.44 2007/06/20 17:29:36 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.45 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.1 1996/09/30 16:34:57 ws Exp $ */ /* @@ -123,7 +123,6 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, sf->sp = (int)cf; sf->user_sr = pmap_kernel()->pm_sr[PPC_USER_SR]; /* just in case */ pcb->pcb_sp = (int)stktop2; - pcb->pcb_spl = 0; } /* @@ -155,8 +154,8 @@ cpu_exit(struct proc *p) pool_put(&ppc_vecpl, pcb->pcb_vr); #endif /* ALTIVEC */ - (void)splsched(); - switchexit(p); + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/sgi/localbus/macebus.c b/sys/arch/sgi/localbus/macebus.c index f02bafba377..4e981dac5ef 100644 --- a/sys/arch/sgi/localbus/macebus.c +++ b/sys/arch/sgi/localbus/macebus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: macebus.c,v 1.26 2007/07/09 21:40:24 jasper Exp $ */ +/* $OpenBSD: macebus.c,v 1.27 2007/10/10 15:53:52 art Exp $ */ /* * Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se) @@ -780,7 +780,6 @@ macebus_iointr(intrmask_t hwpend, struct trap_frame *cf) intrmask_t macebus_aux(intrmask_t hwpend, struct trap_frame *cf) { - extern char idle[], e_idle[]; u_int64_t mask; mask = bus_space_read_8(&macebus_tag, mace_h, MACE_ISA_MISC_REG); @@ -791,7 +790,8 @@ macebus_aux(intrmask_t hwpend, struct trap_frame *cf) /* RED - User Mode */ if (cf->sr & SR_KSU_USER) { mask &= ~MACE_ISA_MISC_RLED_OFF; - } else if (cf->pc >= (long)idle && cf->pc < (long)e_idle) { + } else if (curproc == NULL || + curproc == curcpu()->ci_schedstate.spc_idleproc) { mask &= ~MACE_ISA_MISC_GLED_OFF; } else { mask &= ~(MACE_ISA_MISC_RLED_OFF | MACE_ISA_MISC_GLED_OFF); diff --git a/sys/arch/sgi/sgi/genassym.cf b/sys/arch/sgi/sgi/genassym.cf index a57571199d8..2e5ac9202f8 100644 --- a/sys/arch/sgi/sgi/genassym.cf +++ b/sys/arch/sgi/sgi/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.9 2007/06/18 20:25:55 miod Exp $ +# $OpenBSD: genassym.cf,v 1.10 2007/10/10 15:53:52 art Exp $ # # Copyright (c) 1997 Per Fogelstrom / Opsycon AB # @@ -38,9 +38,7 @@ include <machine/cpu.h> export SONPROC struct proc -member p_forw -member p_back -member p_priority +#member p_priority member p_stat member p_addr #member P_UPTE p_md.md_upte diff --git a/sys/arch/sh/include/cpu.h b/sys/arch/sh/include/cpu.h index b29d7247ce0..8b43e78767b 100644 --- a/sys/arch/sh/include/cpu.h +++ b/sys/arch/sh/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.10 2007/06/06 17:15:12 deraadt Exp $ */ +/* $OpenBSD: cpu.h,v 1.11 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: cpu.h,v 1.41 2006/01/21 04:24:12 uwe Exp $ */ /*- @@ -125,6 +125,11 @@ extern int want_resched; /* need_resched() was called */ * We need a machine-independent name for this. */ #define DELAY(x) delay(x) + +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_cycle() __asm volatile("sleep") +#define cpu_idle_leave() do { /* nothing */ } while (0) + #endif /* _KERNEL */ /* diff --git a/sys/arch/sh/sh/genassym.cf b/sys/arch/sh/sh/genassym.cf index 9227338a9a3..d864f1397ec 100644 --- a/sys/arch/sh/sh/genassym.cf +++ b/sys/arch/sh/sh/genassym.cf @@ -1,4 +1,4 @@ -# $OpenBSD: genassym.cf,v 1.3 2007/05/14 07:05:49 art Exp $ +# $OpenBSD: genassym.cf,v 1.4 2007/10/10 15:53:52 art Exp $ # $NetBSD: genassym.cf,v 1.10 2005/12/11 12:19:00 christos Exp $ #- @@ -54,8 +54,6 @@ member tf_spc struct proc member p_addr -member p_back -member p_forw member p_stat member p_wchan member P_MD_UPTE p_md.md_upte diff --git a/sys/arch/sh/sh/locore_c.c b/sys/arch/sh/sh/locore_c.c index ede226184c7..d1df8aeef7b 100644 --- a/sys/arch/sh/sh/locore_c.c +++ b/sys/arch/sh/sh/locore_c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: locore_c.c,v 1.5 2007/09/09 11:57:55 miod Exp $ */ +/* $OpenBSD: locore_c.c,v 1.6 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: locore_c.c,v 1.13 2006/03/04 01:13:35 uwe Exp $ */ /*- @@ -127,26 +127,14 @@ #include <sh/ubcreg.h> void (*__sh_switch_resume)(struct proc *); -struct proc *cpu_switch_search(struct proc *); -struct proc *cpu_switch_prepare(struct proc *, struct proc *); -void switch_exit(struct proc *, void (*)(struct proc *)); -void idle(void); +void cpu_switch_prepare(struct proc *, struct proc *); int want_resched; -#ifdef LOCKDEBUG -#define SCHED_LOCK_IDLE() sched_lock_idle() -#define SCHED_UNLOCK_IDLE() sched_unlock_idle() -#else -#define SCHED_LOCK_IDLE() do {} while (/* CONSTCOND */ 0) -#define SCHED_UNLOCK_IDLE() do {} while (/* CONSTCOND */ 0) -#endif - - /* * Prepare context switch from oproc to nproc. - * This code is shared by cpu_switch and cpu_switchto. + * This code is used by cpu_switchto. */ -struct proc * +void cpu_switch_prepare(struct proc *oproc, struct proc *nproc) { nproc->p_stat = SONPROC; @@ -154,10 +142,8 @@ cpu_switch_prepare(struct proc *oproc, struct proc *nproc) if (oproc && (oproc->p_md.md_flags & MDP_STEP)) _reg_write_2(SH_(BBRB), 0); - if (nproc != oproc) { - curpcb = nproc->p_md.md_pcb; - pmap_activate(nproc); - } + curpcb = nproc->p_md.md_pcb; + pmap_activate(nproc); if (nproc->p_md.md_flags & MDP_STEP) { int pm_asid = nproc->p_vmspace->vm_map.pmap->pm_asid; @@ -171,34 +157,6 @@ cpu_switch_prepare(struct proc *oproc, struct proc *nproc) } curproc = nproc; - return (nproc); -} - -/* - * Find the highest priority proc and prepare to switching to it. - */ -struct proc * -cpu_switch_search(struct proc *oproc) -{ - struct prochd *q; - struct proc *p; - - curproc = NULL; - - SCHED_LOCK_IDLE(); - while (sched_is_idle()) { - SCHED_UNLOCK_IDLE(); - idle(); - SCHED_LOCK_IDLE(); - } - - q = &qs[ffs(whichqs) - 1]; - p = q->ph_link; - remrunqueue(p); - want_resched = 0; - SCHED_UNLOCK_IDLE(); - - return (cpu_switch_prepare(oproc, p)); } void @@ -207,24 +165,8 @@ cpu_exit(struct proc *p) if (p->p_md.md_flags & MDP_STEP) _reg_write_2(SH_(BBRB), 0); - switch_exit(p, exit2); -} - -/* - * void idle(void): - * When no processes are on the run queue, wait for something to come - * ready. Separated function for profiling. - */ -void -idle() -{ - spl0(); -#if 0 - if (uvm.page_idle_zero) - uvm_pageidlezero(); -#endif - __asm volatile("sleep"); - splsched(); + pmap_deactivate(p); + sched_exit(p); } #ifndef P1_STACK diff --git a/sys/arch/sh/sh/locore_subr.S b/sys/arch/sh/sh/locore_subr.S index de57709a5d5..5543b4870c6 100644 --- a/sys/arch/sh/sh/locore_subr.S +++ b/sys/arch/sh/sh/locore_subr.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore_subr.S,v 1.6 2007/03/02 06:11:54 miod Exp $ */ +/* $OpenBSD: locore_subr.S,v 1.7 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: locore_subr.S,v 1.28 2006/01/23 22:52:09 uwe Exp $ */ /* @@ -180,27 +180,26 @@ .text .align 5 /* align cache line size (32B) */ /* - * LINTSTUB: Func: void cpu_switch(struct proc *p, struct proc *XXX_IGNORED) - * Find a runnable proc and switch to it. Wait if necessary. + * LINTSTUB: Func: void cpu_switchto(struct proc *old, struct proc *new) + * Switch proc contexts. */ -ENTRY(cpu_switch) - /* Save current proc's context to switchframe */ +ENTRY(cpu_switchto) + mov r4, r0 + cmp/eq #0, r0 + bt 1f + + /* Save old proc's context to switchframe */ mov.l .L_SF, r0 mov.l @(r0, r4), r1 SAVEPCB(r1) add #PCB_FP, r1 SAVEFP(r1, r8, r9) -.L_find_and_switch: - /* Search next proc. cpu_switch_search may or may not sleep. */ - mov.l .L_cpu_switch_search, r0 +1: + mov.l .L_cpu_switch_prepare, r0 jsr @r0 - mov r4, r8 /* save old proc */ - - /* Skip context switch if same proc. */ - cmp/eq r8, r0 - bt/s 1f - mov r0, r4 /* new proc */ + mov r5, r8 /* save new proc */ + mov r8, r4 /* Setup kernel stack */ mov.l .L_SF, r0 @@ -224,7 +223,7 @@ ENTRY(cpu_switch) /* Now OK to use kernel stack. */ /* Restore new proc's context from switchframe */ -1: mov.l .L_SF, r0 + mov.l .L_SF, r0 mov.l @(r0, r4), r1 add #4, r1 /* r15 already restored */ mov.l @r1+, r14 @@ -248,49 +247,9 @@ ENTRY(cpu_switch) nop .align 2 .L_SF: .long (P_MD_PCB) -.L_cpu_switch_search: .long _C_LABEL(cpu_switch_search) +.L_cpu_switch_prepare: .long _C_LABEL(cpu_switch_prepare) FUNC_SYMBOL(switch_resume) - -/* - * LINTSTUB: Func: void switch_exit(struct proc *p, void (*exit_func)(struct proc *)) - * Called only from cpu_exit(p). Before we call exit_func to - * free proc's resources (including kernel stack) we need to - * switch to the proc0's kernel stack. Then we jump into the - * middle of cpu_switch to find and switch to a new proc. - */ -ALTENTRY(switch_exit) - mov.l .L_switch_exit_proc0_pcb, r1 - mov.l .L_switch_exit_curpcb, r0 - mov.l @r1, r1 - mov.l r1, @r0 /* curpcb = proc0.p_md.md_pcb */ - - mov.l @(SF_R7_BANK, r1), r0 /* stack top */ - mov.l @(SF_R6_BANK, r1), r2 /* current frame */ - mov.l @(SF_R15, r1), r3 /* current stack */ - - /* switch to proc0's kernel stack */ - __EXCEPTION_BLOCK(r1, r6) - ldc r0, r7_bank - ldc r2, r6_bank - mov r3, r15 - __EXCEPTION_UNBLOCK(r0, r1) - - /* safe to call (*exit_func)(p); now */ - jsr @r5 - nop /* proc is already in r4 */ - - /* proceed to cpu_switch */ - bra .L_find_and_switch - mov #0, r4 /* no "previous" proc */ - - .align 2 -.L_switch_exit_proc0_pcb: - .long _C_LABEL(proc0) + P_MD_PCB -.L_switch_exit_curpcb: - .long _C_LABEL(curpcb) - - #ifdef SH3 /* * LINTSTUB: Func: void sh3_switch_resume(struct proc *p) diff --git a/sys/arch/sh/sh/sh_machdep.c b/sys/arch/sh/sh/sh_machdep.c index d81017ac0f1..0cfcd801825 100644 --- a/sys/arch/sh/sh/sh_machdep.c +++ b/sys/arch/sh/sh/sh_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sh_machdep.c,v 1.16 2007/06/06 17:15:12 deraadt Exp $ */ +/* $OpenBSD: sh_machdep.c,v 1.17 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: sh3_machdep.c,v 1.59 2006/03/04 01:13:36 uwe Exp $ */ /* @@ -716,45 +716,6 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, rval[1] = 0; } -void -setrunqueue(struct proc *p) -{ - int whichq = p->p_priority / PPQ; - struct prochd *q; - struct proc *prev; - -#ifdef DIAGNOSTIC - if (p->p_back != NULL || p->p_wchan != NULL || p->p_stat != SRUN) - panic("setrunqueue"); -#endif - q = &qs[whichq]; - prev = q->ph_rlink; - p->p_forw = (struct proc *)q; - q->ph_rlink = p; - prev->p_forw = p; - p->p_back = prev; - whichqs |= 1 << whichq; -} - -void -remrunqueue(struct proc *p) -{ - struct proc *prev, *next; - int whichq = p->p_priority / PPQ; - -#ifdef DIAGNOSTIC - if (((whichqs & (1 << whichq)) == 0)) - panic("remrunqueue: bit %d not set", whichq); -#endif - prev = p->p_back; - p->p_back = NULL; - next = p->p_forw; - prev->p_forw = next; - next->p_back = prev; - if (prev == next) - whichqs &= ~(1 << whichq); -} - /* * Jump to reset vector. */ diff --git a/sys/arch/solbourne/solbourne/locore.s b/sys/arch/solbourne/solbourne/locore.s index 8ff5842d209..0c8666cb599 100644 --- a/sys/arch/solbourne/solbourne/locore.s +++ b/sys/arch/solbourne/solbourne/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.8 2006/04/15 17:36:47 miod Exp $ */ +/* $OpenBSD: locore.s,v 1.9 2007/10/10 15:53:52 art Exp $ */ /* OpenBSD: locore.s,v 1.64 2005/04/17 18:47:50 miod Exp */ /* @@ -3233,291 +3233,52 @@ ENTRY(write_user_windows) .comm _C_LABEL(masterpaddr), 4 /* - * Switch statistics (for later tweaking): - * nswitchdiff = p1 => p2 (i.e., chose different process) - * nswitchexit = number of calls to switchexit() - * _cnt.v_swtch = total calls to swtch+swtchexit + * cpu_switchto(struct proc *oldproc, struct proc *newproc) */ - .comm _C_LABEL(nswitchdiff), 4 - .comm _C_LABEL(nswitchexit), 4 - -/* - * REGISTER USAGE IN cpu_switch AND switchexit: - * This is split into two phases, more or less - * `before we locate a new proc' and `after'. - * Some values are the same in both phases. - * Note that the %o0-registers are not preserved across - * the psr change when entering a new process, since this - * usually changes the CWP field (hence heavy usage of %g's). - * - * %g1 = oldpsr (excluding ipl bits) - * %g2 = %hi(_C_LABEL(whichqs)); newpsr - * %g3 = p - * %g4 = lastproc - * %g5 = <free>; newpcb - * %g6 = %hi(_C_LABEL(cpcb)) - * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4; whichqs; vm - * %o4 = tmp 4; which; sswap - * %o5 = tmp 5; q; <free> - */ - -/* - * switchexit is called only from cpu_exit() before the current process - * has freed its kernel stack; we must free it. (curproc is already NULL.) - * - * We lay the process to rest by changing to the `idle' kernel stack, - * and note that the `last loaded process' is nonexistent. - */ -ENTRY(switchexit) - mov %o0, %g2 ! save proc for exit2() call - - /* - * Change pcb to idle u. area, i.e., set %sp to top of stack - * and %psr to PSR_S|PSR_ET, and set cpcb to point to _idle_u. - * Once we have left the old stack, we can call kmem_free to - * destroy it. Call it any sooner and the register windows - * go bye-bye. - */ - set _C_LABEL(idle_u), %g5 - sethi %hi(_C_LABEL(cpcb)), %g6 - mov 1, %g7 - wr %g0, PSR_S, %psr ! change to window 0, traps off - nop; nop; nop - wr %g0, 2, %wim ! and make window 1 the trap window - st %g5, [%g6 + %lo(_C_LABEL(cpcb))] ! cpcb = &idle_u - st %g7, [%g5 + PCB_WIM] ! idle_u.pcb_wim = log2(2) = 1 - set _C_LABEL(idle_u) + USPACE-CCFSZ, %sp ! set new %sp -#ifdef DEBUG - set _C_LABEL(idle_u), %l6 - SET_SP_REDZONE(%l6, %l5) -#endif - wr %g0, PSR_S|PSR_ET, %psr ! and then enable traps - call _C_LABEL(exit2) ! exit2(p) - mov %g2, %o0 - - /* - * Now fall through to `the last switch'. %g6 was set to - * %hi(_C_LABEL(cpcb)), but may have been clobbered in kmem_free, - * so all the registers described below will be set here. - * - * REGISTER USAGE AT THIS POINT: - * %g1 = oldpsr (excluding ipl bits) - * %g2 = %hi(_C_LABEL(whichqs)) - * %g4 = lastproc - * %g6 = %hi(_C_LABEL(cpcb)) - * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o3 = whichqs - */ - - INCR(_C_LABEL(nswitchexit)) ! nswitchexit++; - INCR(_C_LABEL(uvmexp)+V_SWTCH) ! cnt.v_switch++; - - mov PSR_S|PSR_ET, %g1 ! oldpsr = PSR_S | PSR_ET; - sethi %hi(_C_LABEL(whichqs)), %g2 - clr %g4 ! lastproc = NULL; +ENTRY(cpu_switchto) sethi %hi(_C_LABEL(cpcb)), %g6 sethi %hi(_C_LABEL(curproc)), %g7 - /* FALLTHROUGH */ - -/* - * When no processes are on the runq, switch - * idles here waiting for something to come ready. - * The registers are set up as noted above. - */ - .globl idle -idle: - st %g0, [%g7 + %lo(_C_LABEL(curproc))] ! curproc = NULL; - wr %g1, 0, %psr ! (void) spl0(); -1: ! spin reading _whichqs until nonzero - ld [%g2 + %lo(_C_LABEL(whichqs))], %o3 - tst %o3 - bnz,a Lsw_scan - wr %g1, IPL_CLOCK << 8, %psr ! (void) splclock(); - b,a 1b - -Lsw_panic_rq: - sethi %hi(1f), %o0 - call _C_LABEL(panic) - or %lo(1f), %o0, %o0 -Lsw_panic_wchan: - sethi %hi(2f), %o0 - call _C_LABEL(panic) - or %lo(2f), %o0, %o0 -Lsw_panic_srun: - sethi %hi(3f), %o0 - call _C_LABEL(panic) - or %lo(3f), %o0, %o0 -1: .asciz "switch rq" -2: .asciz "switch wchan" -3: .asciz "switch SRUN" - _ALIGN - -/* - * cpu_switch() picks a process to run and runs it, saving the current - * one away. On the assumption that (since most workstations are - * single user machines) the chances are quite good that the new - * process will turn out to be the current process, we defer saving - * it here until we have found someone to load. If that someone - * is the current process we avoid both store and load. - * - * cpu_switch() is always entered at splstatclock or splhigh. - * - * IT MIGHT BE WORTH SAVING BEFORE ENTERING idle TO AVOID HAVING TO - * SAVE LATER WHEN SOMEONE ELSE IS READY ... MUST MEASURE! - */ - .globl _C_LABEL(time) -ENTRY(cpu_switch) - /* - * REGISTER USAGE AT THIS POINT: - * %g1 = oldpsr (excluding ipl bits) - * %g2 = %hi(_C_LABEL(whichqs)) - * %g3 = p - * %g4 = lastproc - * %g5 = tmp 0 - * %g6 = %hi(_C_LABEL(cpcb)) - * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4, then at Lsw_scan, whichqs - * %o4 = tmp 5, then at Lsw_scan, which - * %o5 = tmp 6, then at Lsw_scan, q - */ - sethi %hi(_C_LABEL(whichqs)), %g2 ! set up addr regs - sethi %hi(_C_LABEL(cpcb)), %g6 - ld [%g6 + %lo(_C_LABEL(cpcb))], %o0 - std %o6, [%o0 + PCB_SP] ! cpcb->pcb_<sp,pc> = <sp,pc>; + ld [%g6 + %lo(_C_LABEL(cpcb))], %o2 + std %o6, [%o2 + PCB_SP] ! cpcb->pcb_<sp,pc> = <sp,pc>; rd %psr, %g1 ! oldpsr = %psr; - sethi %hi(_C_LABEL(curproc)), %g7 - ld [%g7 + %lo(_C_LABEL(curproc))], %g4 ! lastproc = curproc; - st %g1, [%o0 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; + st %g1, [%o2 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; andn %g1, PSR_PIL, %g1 ! oldpsr &= ~PSR_PIL; /* - * In all the fiddling we did to get this far, the thing we are - * waiting for might have come ready, so let interrupts in briefly - * before checking for other processes. Note that we still have - * curproc set---we have to fix this or we can get in trouble with - * the run queues below. - */ - st %g0, [%g7 + %lo(_C_LABEL(curproc))] ! curproc = NULL; - wr %g1, 0, %psr ! (void) spl0(); - nop; nop; nop ! paranoia - wr %g1, IPL_CLOCK << 8 , %psr ! (void) splclock(); - -Lsw_scan: - nop; nop; nop ! paranoia - ld [%g2 + %lo(_C_LABEL(whichqs))], %o3 - - /* - * Optimized inline expansion of `which = ffs(whichqs) - 1'; - * branches to idle if ffs(whichqs) was 0. - */ - set ffstab, %o2 - andcc %o3, 0xff, %o1 ! byte 0 zero? - bz,a 1f ! yes, try byte 1 - srl %o3, 8, %o0 - b 2f ! ffs = ffstab[byte0]; which = ffs - 1; - ldsb [%o2 + %o1], %o0 -1: andcc %o0, 0xff, %o1 ! byte 1 zero? - bz,a 1f ! yes, try byte 2 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte1] + 7; - b 3f - add %o0, 7, %o4 -1: andcc %o0, 0xff, %o1 ! byte 2 zero? - bz,a 1f ! yes, try byte 3 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte2] + 15; - b 3f - add %o0, 15, %o4 -1: ldsb [%o2 + %o0], %o0 ! ffs = ffstab[byte3] + 24 - addcc %o0, 24, %o0 ! (note that ffstab[0] == -24) - bz idle ! if answer was 0, go idle - EMPTY -2: sub %o0, 1, %o4 ! which = ffs(whichqs) - 1 -3: /* end optimized inline expansion */ - - /* - * We found a nonempty run queue. Take its first process. - */ - set _C_LABEL(qs), %o5 ! q = &qs[which]; - sll %o4, 3, %o0 - add %o0, %o5, %o5 - ld [%o5], %g3 ! p = q->ph_link; - cmp %g3, %o5 ! if (p == q) - be Lsw_panic_rq ! panic("switch rq"); - EMPTY - ld [%g3], %o0 ! tmp0 = p->p_forw; - st %o0, [%o5] ! q->ph_link = tmp0; - st %o5, [%o0 + 4] ! tmp0->p_back = q; - cmp %o0, %o5 ! if (tmp0 == q) - bne 1f - EMPTY - mov 1, %o1 ! whichqs &= ~(1 << which); - sll %o1, %o4, %o1 - andn %o3, %o1, %o3 - st %o3, [%g2 + %lo(_C_LABEL(whichqs))] -1: - /* - * PHASE TWO: NEW REGISTER USAGE: + * REGISTER USAGE: * %g1 = oldpsr (excluding ipl bits) * %g2 = newpsr - * %g3 = p - * %g4 = lastproc * %g5 = newpcb * %g6 = %hi(_C_LABEL(cpcb)) * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 + * %o0 = oldproc + * %o1 = newproc * %o2 = tmp 3 * %o3 = vm * %o4 = sswap * %o5 = <free> */ - /* firewalls */ - ld [%g3 + P_WCHAN], %o0 ! if (p->p_wchan) - tst %o0 - bne Lsw_panic_wchan ! panic("switch wchan"); - EMPTY - ldsb [%g3 + P_STAT], %o0 ! if (p->p_stat != SRUN) - cmp %o0, SRUN - bne Lsw_panic_srun ! panic("switch SRUN"); - EMPTY - /* - * Committed to running process p. - * It may be the same as the one we were running before. + * Committed to running process p (in o1). */ + mov %o1, %g3 + mov SONPROC, %o0 ! p->p_stat = SONPROC stb %o0, [%g3 + P_STAT] sethi %hi(_C_LABEL(want_resched)), %o0 st %g0, [%o0 + %lo(_C_LABEL(want_resched))] ! want_resched = 0; ld [%g3 + P_ADDR], %g5 ! newpcb = p->p_addr; - st %g0, [%g3 + 4] ! p->p_back = NULL; ld [%g5 + PCB_PSR], %g2 ! newpsr = newpcb->pcb_psr; st %g3, [%g7 + %lo(_C_LABEL(curproc))] ! curproc = p; - cmp %g3, %g4 ! p == lastproc? - be,a Lsw_sameproc ! yes, go return 0 - wr %g2, 0, %psr ! (after restoring ipl) - /* - * Not the old process. Save the old process, if any; - * then load p. + * Save the old process, if any; then load p. */ - tst %g4 + tst %o0 be,a Lsw_load ! if no old process, go load wr %g1, (IPL_CLOCK << 8) | PSR_ET, %psr - INCR(_C_LABEL(nswitchdiff)) ! clobbers %o0,%o1 /* * save: write back all windows (including the current one). * XXX crude; knows nwindows <= 8 @@ -3659,16 +3420,17 @@ badstack: */ retl - EMPTY -1: + nop -Lsw_sameproc: - /* - * We are resuming the process that was running at the - * call to switch(). Just set psr ipl and return. - */ -! wr %g2, 0 %psr ! %psr = newpsr; (done earlier) - nop +ENTRY(cpu_idle_enter) + retl + nop + +ENTRY(cpu_idle_cycle) + retl + nop + +ENTRY(cpu_idle_leave) retl nop diff --git a/sys/arch/sparc/conf/files.sparc b/sys/arch/sparc/conf/files.sparc index 00110dace96..1e4de8736a5 100644 --- a/sys/arch/sparc/conf/files.sparc +++ b/sys/arch/sparc/conf/files.sparc @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc,v 1.78 2007/05/29 09:54:03 sobrado Exp $ +# $OpenBSD: files.sparc,v 1.79 2007/10/10 15:53:52 art Exp $ # $NetBSD: files.sparc,v 1.44 1997/08/31 21:29:16 pk Exp $ # @(#)files.sparc 8.1 (Berkeley) 7/19/93 @@ -291,7 +291,6 @@ file arch/sparc/sparc/emul.c file arch/sparc/sparc/in_cksum.c inet file arch/sparc/sparc/intr.c file arch/sparc/sparc/kgdb_machdep.c kgdb -file arch/sparc/sparc/locore2.c file arch/sparc/sparc/machdep.c !solbourne file arch/sparc/sparc/mem.c !solbourne file arch/sparc/sparc/mutex.c diff --git a/sys/arch/sparc/sparc/locore.s b/sys/arch/sparc/sparc/locore.s index 580d51bf563..ac109ebffeb 100644 --- a/sys/arch/sparc/sparc/locore.s +++ b/sys/arch/sparc/sparc/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.72 2007/05/29 09:54:01 sobrado Exp $ */ +/* $OpenBSD: locore.s,v 1.73 2007/10/10 15:53:52 art Exp $ */ /* $NetBSD: locore.s,v 1.73 1997/09/13 20:36:48 pk Exp $ */ /* @@ -4383,290 +4383,52 @@ ENTRY(write_user_windows) .comm _C_LABEL(masterpaddr), 4 /* - * Switch statistics (for later tweaking): - * nswitchdiff = p1 => p2 (i.e., chose different process) - * nswitchexit = number of calls to switchexit() - * _cnt.v_swtch = total calls to swtch+swtchexit + * cpu_switchto(struct proc *oldproc, struct proc *newproc) */ - .comm _C_LABEL(nswitchdiff), 4 - .comm _C_LABEL(nswitchexit), 4 - -/* - * REGISTER USAGE IN cpu_switch AND switchexit: - * This is split into two phases, more or less - * `before we locate a new proc' and `after'. - * Some values are the same in both phases. - * Note that the %o0-registers are not preserved across - * the psr change when entering a new process, since this - * usually changes the CWP field (hence heavy usage of %g's). - * - * %g1 = oldpsr (excluding ipl bits) - * %g2 = %hi(_C_LABEL(whichqs)); newpsr - * %g3 = p - * %g4 = lastproc - * %g5 = <free>; newpcb - * %g6 = %hi(_C_LABEL(cpcb)) - * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4; whichqs; vm - * %o4 = tmp 4; which; sswap - * %o5 = tmp 5; q; <free> - */ - -/* - * switchexit is called only from cpu_exit() before the current process - * has freed its kernel stack; we must free it. (curproc is already NULL.) - * - * We lay the process to rest by changing to the `idle' kernel stack, - * and note that the `last loaded process' is nonexistent. - */ -ENTRY(switchexit) - mov %o0, %g2 ! save proc for exit2() call - - /* - * Change pcb to idle u. area, i.e., set %sp to top of stack - * and %psr to PSR_S|PSR_ET, and set cpcb to point to _idle_u. - * Once we have left the old stack, we can call kmem_free to - * destroy it. Call it any sooner and the register windows - * go bye-bye. - */ - set _C_LABEL(idle_u), %g5 - sethi %hi(_C_LABEL(cpcb)), %g6 - mov 1, %g7 - wr %g0, PSR_S, %psr ! change to window 0, traps off - wr %g0, 2, %wim ! and make window 1 the trap window - st %g5, [%g6 + %lo(_C_LABEL(cpcb))] ! cpcb = &idle_u - st %g7, [%g5 + PCB_WIM] ! idle_u.pcb_wim = log2(2) = 1 - set _C_LABEL(idle_u) + USPACE-CCFSZ, %sp ! set new %sp -#ifdef DEBUG - set _C_LABEL(idle_u), %l6 - SET_SP_REDZONE(%l6, %l5) -#endif - wr %g0, PSR_S|PSR_ET, %psr ! and then enable traps - call _C_LABEL(exit2) ! exit2(p) - mov %g2, %o0 - - /* - * Now fall through to `the last switch'. %g6 was set to - * %hi(_C_LABEL(cpcb)), but may have been clobbered in kmem_free, - * so all the registers described below will be set here. - * - * REGISTER USAGE AT THIS POINT: - * %g1 = oldpsr (excluding ipl bits) - * %g2 = %hi(_C_LABEL(whichqs)) - * %g4 = lastproc - * %g6 = %hi(_C_LABEL(cpcb)) - * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o3 = whichqs - */ - - INCR(_C_LABEL(nswitchexit)) ! nswitchexit++; - INCR(_C_LABEL(uvmexp)+V_SWTCH) ! cnt.v_switch++; - - mov PSR_S|PSR_ET, %g1 ! oldpsr = PSR_S | PSR_ET; - sethi %hi(_C_LABEL(whichqs)), %g2 - clr %g4 ! lastproc = NULL; +ENTRY(cpu_switchto) sethi %hi(_C_LABEL(cpcb)), %g6 sethi %hi(_C_LABEL(curproc)), %g7 - /* FALLTHROUGH */ - -/* - * When no processes are on the runq, switch - * idles here waiting for something to come ready. - * The registers are set up as noted above. - */ - .globl idle -idle: - st %g0, [%g7 + %lo(_C_LABEL(curproc))] ! curproc = NULL; - wr %g1, 0, %psr ! (void) spl0(); -1: ! spin reading _whichqs until nonzero - ld [%g2 + %lo(_C_LABEL(whichqs))], %o3 - tst %o3 - bnz,a Lsw_scan - wr %g1, IPL_CLOCK << 8, %psr ! (void) splclock(); - b,a 1b - -Lsw_panic_rq: - sethi %hi(1f), %o0 - call _C_LABEL(panic) - or %lo(1f), %o0, %o0 -Lsw_panic_wchan: - sethi %hi(2f), %o0 - call _C_LABEL(panic) - or %lo(2f), %o0, %o0 -Lsw_panic_srun: - sethi %hi(3f), %o0 - call _C_LABEL(panic) - or %lo(3f), %o0, %o0 -1: .asciz "switch rq" -2: .asciz "switch wchan" -3: .asciz "switch SRUN" - _ALIGN - -/* - * cpu_switch() picks a process to run and runs it, saving the current - * one away. On the assumption that (since most workstations are - * single user machines) the chances are quite good that the new - * process will turn out to be the current process, we defer saving - * it here until we have found someone to load. If that someone - * is the current process we avoid both store and load. - * - * cpu_switch() is always entered at splstatclock or splhigh. - * - * IT MIGHT BE WORTH SAVING BEFORE ENTERING idle TO AVOID HAVING TO - * SAVE LATER WHEN SOMEONE ELSE IS READY ... MUST MEASURE! - */ - .globl _C_LABEL(time) -ENTRY(cpu_switch) - /* - * REGISTER USAGE AT THIS POINT: - * %g1 = oldpsr (excluding ipl bits) - * %g2 = %hi(_C_LABEL(whichqs)) - * %g3 = p - * %g4 = lastproc - * %g5 = tmp 0 - * %g6 = %hi(_C_LABEL(cpcb)) - * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4, then at Lsw_scan, whichqs - * %o4 = tmp 5, then at Lsw_scan, which - * %o5 = tmp 6, then at Lsw_scan, q - */ - sethi %hi(_C_LABEL(whichqs)), %g2 ! set up addr regs - sethi %hi(_C_LABEL(cpcb)), %g6 - ld [%g6 + %lo(_C_LABEL(cpcb))], %o0 - std %o6, [%o0 + PCB_SP] ! cpcb->pcb_<sp,pc> = <sp,pc>; + ld [%g6 + %lo(_C_LABEL(cpcb))], %o2 + std %o6, [%o2 + PCB_SP] ! cpcb->pcb_<sp,pc> = <sp,pc>; rd %psr, %g1 ! oldpsr = %psr; - sethi %hi(_C_LABEL(curproc)), %g7 - ld [%g7 + %lo(_C_LABEL(curproc))], %g4 ! lastproc = curproc; - st %g1, [%o0 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; + st %g1, [%o2 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; andn %g1, PSR_PIL, %g1 ! oldpsr &= ~PSR_PIL; /* - * In all the fiddling we did to get this far, the thing we are - * waiting for might have come ready, so let interrupts in briefly - * before checking for other processes. Note that we still have - * curproc set---we have to fix this or we can get in trouble with - * the run queues below. - */ - st %g0, [%g7 + %lo(_C_LABEL(curproc))] ! curproc = NULL; - wr %g1, 0, %psr ! (void) spl0(); - nop; nop; nop ! paranoia - wr %g1, IPL_CLOCK << 8 , %psr ! (void) splclock(); - -Lsw_scan: - nop; nop; nop ! paranoia - ld [%g2 + %lo(_C_LABEL(whichqs))], %o3 - - /* - * Optimized inline expansion of `which = ffs(whichqs) - 1'; - * branches to idle if ffs(whichqs) was 0. - */ - set ffstab, %o2 - andcc %o3, 0xff, %o1 ! byte 0 zero? - bz,a 1f ! yes, try byte 1 - srl %o3, 8, %o0 - b 2f ! ffs = ffstab[byte0]; which = ffs - 1; - ldsb [%o2 + %o1], %o0 -1: andcc %o0, 0xff, %o1 ! byte 1 zero? - bz,a 1f ! yes, try byte 2 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte1] + 7; - b 3f - add %o0, 7, %o4 -1: andcc %o0, 0xff, %o1 ! byte 2 zero? - bz,a 1f ! yes, try byte 3 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte2] + 15; - b 3f - add %o0, 15, %o4 -1: ldsb [%o2 + %o0], %o0 ! ffs = ffstab[byte3] + 24 - addcc %o0, 24, %o0 ! (note that ffstab[0] == -24) - bz idle ! if answer was 0, go idle - EMPTY -2: sub %o0, 1, %o4 ! which = ffs(whichqs) - 1 -3: /* end optimized inline expansion */ - - /* - * We found a nonempty run queue. Take its first process. - */ - set _C_LABEL(qs), %o5 ! q = &qs[which]; - sll %o4, 3, %o0 - add %o0, %o5, %o5 - ld [%o5], %g3 ! p = q->ph_link; - cmp %g3, %o5 ! if (p == q) - be Lsw_panic_rq ! panic("switch rq"); - EMPTY - ld [%g3], %o0 ! tmp0 = p->p_forw; - st %o0, [%o5] ! q->ph_link = tmp0; - st %o5, [%o0 + 4] ! tmp0->p_back = q; - cmp %o0, %o5 ! if (tmp0 == q) - bne 1f - EMPTY - mov 1, %o1 ! whichqs &= ~(1 << which); - sll %o1, %o4, %o1 - andn %o3, %o1, %o3 - st %o3, [%g2 + %lo(_C_LABEL(whichqs))] -1: - /* - * PHASE TWO: NEW REGISTER USAGE: + * REGISTER USAGE: * %g1 = oldpsr (excluding ipl bits) * %g2 = newpsr - * %g3 = p - * %g4 = lastproc * %g5 = newpcb * %g6 = %hi(_C_LABEL(cpcb)) * %g7 = %hi(_C_LABEL(curproc)) - * %o0 = tmp 1 - * %o1 = tmp 2 + * %o0 = oldproc + * %o1 = newproc * %o2 = tmp 3 * %o3 = vm * %o4 = sswap * %o5 = <free> */ - /* firewalls */ - ld [%g3 + P_WCHAN], %o0 ! if (p->p_wchan) - tst %o0 - bne Lsw_panic_wchan ! panic("switch wchan"); - EMPTY - ldsb [%g3 + P_STAT], %o0 ! if (p->p_stat != SRUN) - cmp %o0, SRUN - bne Lsw_panic_srun ! panic("switch SRUN"); - EMPTY - /* - * Committed to running process p. - * It may be the same as the one we were running before. + * Committed to running process p (in o1). */ + mov %o1, %g3 + mov SONPROC, %o0 ! p->p_stat = SONPROC stb %o0, [%g3 + P_STAT] sethi %hi(_C_LABEL(want_resched)), %o0 st %g0, [%o0 + %lo(_C_LABEL(want_resched))] ! want_resched = 0; ld [%g3 + P_ADDR], %g5 ! newpcb = p->p_addr; - st %g0, [%g3 + 4] ! p->p_back = NULL; ld [%g5 + PCB_PSR], %g2 ! newpsr = newpcb->pcb_psr; st %g3, [%g7 + %lo(_C_LABEL(curproc))] ! curproc = p; - cmp %g3, %g4 ! p == lastproc? - be,a Lsw_sameproc ! yes, go return 0 - wr %g2, 0, %psr ! (after restoring ipl) - /* - * Not the old process. Save the old process, if any; - * then load p. + * Save the old process, if any; then load p. */ - tst %g4 + tst %o0 be,a Lsw_load ! if no old process, go load wr %g1, (IPL_CLOCK << 8) | PSR_ET, %psr - INCR(_C_LABEL(nswitchdiff)) ! clobbers %o0,%o1 /* * save: write back all windows (including the current one). * XXX crude; knows nwindows <= 8 @@ -4773,16 +4535,17 @@ Lsw_havectx: sta %o0, [%o1] ASI_SRMMU ! setcontext(vm->vm_map.pmap->pm_ctxnum); #endif -Lsw_sameproc: - /* - * We are resuming the process that was running at the - * call to switch(). Just set psr ipl and return. - */ -! wr %g2, 0 %psr ! %psr = newpsr; (done earlier) - nop +ENTRY(cpu_idle_enter) retl nop +ENTRY(cpu_idle_cycle) + retl + nop + +ENTRY(cpu_idle_leave) + retl + nop /* * Snapshot the current process so that stack frames are up to date. diff --git a/sys/arch/sparc/sparc/locore2.c b/sys/arch/sparc/sparc/locore2.c index f2b90ed0e4a..e69de29bb2d 100644 --- a/sys/arch/sparc/sparc/locore2.c +++ b/sys/arch/sparc/sparc/locore2.c @@ -1,99 +0,0 @@ -/* $OpenBSD: locore2.c,v 1.5 2003/06/02 23:27:55 millert Exp $ */ -/* $NetBSD: locore2.c,v 1.7 1996/11/06 20:19:53 cgd Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory. - * - * 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. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)locore2.c 8.4 (Berkeley) 12/10/93 - */ - -/* - * Primitives which are in locore.s on other machines, - * but which have no reason to be assembly-coded on SPARC. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/resourcevar.h> - -#include <machine/cpu.h> - -int whichqs; - -/* - * Put process p on the run queue indicated by its priority. - * Calls should be made at splstatclock(), and p->p_stat should be SRUN. - */ -void -setrunqueue(p) - register struct proc *p; -{ - register struct prochd *q; - register struct proc *oldlast; - register int which = p->p_priority >> 2; - - if (p->p_back != NULL) - panic("setrunqueue"); - q = &qs[which]; - whichqs |= 1 << which; - p->p_forw = (struct proc *)q; - p->p_back = oldlast = q->ph_rlink; - q->ph_rlink = p; - oldlast->p_forw = p; -} - -/* - * Remove process p from its run queue, which should be the one - * indicated by its priority. Calls should be made at splstatclock(). - */ -void -remrunqueue(p) - register struct proc *p; -{ - register int which = p->p_priority >> 2; - register struct prochd *q; - - if ((whichqs & (1 << which)) == 0) - panic("remrunqueue"); - p->p_forw->p_back = p->p_back; - p->p_back->p_forw = p->p_forw; - p->p_back = NULL; - q = &qs[which]; - if (q->ph_link == (struct proc *)q) - whichqs &= ~(1 << which); -} diff --git a/sys/arch/sparc/sparc/vm_machdep.c b/sys/arch/sparc/sparc/vm_machdep.c index 73bbdfb1b45..97f5ee4adc1 100644 --- a/sys/arch/sparc/sparc/vm_machdep.c +++ b/sys/arch/sparc/sparc/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.49 2007/06/20 17:29:36 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.50 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.30 1997/03/10 23:55:40 pk Exp $ */ /* @@ -449,10 +449,9 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) /* * cpu_exit is called as the last action during exit. * - * We clean up a little and then call switchexit() with the old proc - * as an argument. switchexit() switches to the idle context, schedules - * the old vmspace and stack to be freed, then selects a new process to - * run. + * We clean up a little and then call sched_exit() with the old proc + * as an argument. sched_exit() schedules the old vmspace and stack + * to be freed, then selects a new process to run. */ void cpu_exit(p) @@ -468,8 +467,8 @@ cpu_exit(p) free((void *)fs, M_SUBPROC); } - switchexit(p); - /* NOTREACHED */ + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/sparc64/conf/files.sparc64 b/sys/arch/sparc64/conf/files.sparc64 index f3463fa8aa8..c9150465f13 100644 --- a/sys/arch/sparc64/conf/files.sparc64 +++ b/sys/arch/sparc64/conf/files.sparc64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc64,v 1.89 2007/09/10 21:33:16 kettenis Exp $ +# $OpenBSD: files.sparc64,v 1.90 2007/10/10 15:53:53 art Exp $ # $NetBSD: files.sparc64,v 1.50 2001/08/10 20:53:50 eeh Exp $ # maxpartitions must be first item in files.${ARCH} @@ -243,7 +243,6 @@ file arch/sparc64/sparc64/ipifuncs.c multiprocessor file arch/sparc64/sparc64/kgdb_machdep.c kgdb # sparc64/sparc64/locore.s is handled specially in the makefile, # because it must come first in the "ld" command line. -file arch/sparc64/sparc64/locore2.c file arch/sparc64/sparc64/machdep.c file arch/sparc64/sparc64/mem.c file arch/sparc64/sparc64/mutex.S diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index 07767d70bc5..2456810258e 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.83 2007/09/30 21:34:20 kettenis Exp $ */ +/* $OpenBSD: locore.s,v 1.84 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */ /* @@ -5573,350 +5573,39 @@ Lcopyfault: retl mov EFAULT, %o0 - - .data - _ALIGN -/* - * Switch statistics (for later tweaking): - * nswitchdiff = p1 => p2 (i.e., chose different process) - * nswitchexit = number of calls to switchexit() - * _cnt.v_swtch = total calls to swtch+swtchexit - */ - .comm _C_LABEL(nswitchdiff), 4 - .comm _C_LABEL(nswitchexit), 4 - .text -/* - * REGISTER USAGE IN cpu_switch AND switchexit: - * This is split into two phases, more or less - * `before we locate a new proc' and `after'. - * Some values are the same in both phases. - * Note that the %o0-registers are not preserved across - * the psr change when entering a new process, since this - * usually changes the CWP field (hence heavy usage of %g's). - * - * %l1 = <free>; newpcb - * %l2 = %hi(_whichqs); newpsr - * %l3 = p - * %l4 = lastproc - * %l5 = oldpsr (excluding ipl bits) - * %l6 = %hi(cpcb) - * %l7 = %hi(curproc) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4; whichqs; vm - * %o4 = tmp 4; which; sswap - * %o5 = tmp 5; q; <free> - */ - -/* - * switchexit is called only from cpu_exit() before the current process - * has freed its vmspace and kernel stack; we must schedule them to be - * freed. (curproc is already NULL.) - * - * We lay the process to rest by changing to the `idle' kernel stack, - * and note that the `last loaded process' is nonexistent. - */ -ENTRY(switchexit) - /* - * Since we're exiting we don't need to save locals or ins, so - * we won't need the next instruction. - */ -! save %sp, -CC64FSZ, %sp - flushw ! We don't have anything else to run, so why not -#ifdef DEBUG - save %sp, -CC64FSZ, %sp - flushw - restore -#endif /* DEBUG */ - wrpr %g0, PSTATE_KERN, %pstate ! Make sure we're on the right globals - mov %o0, %l2 ! save proc arg for exit2() call XXXXX - - /* - * Change pcb to idle u. area, i.e., set %sp to top of stack - * and %psr to PSR_S|PSR_ET, and set cpcb to point to _idle_u. - * Once we have left the old stack, we can call kmem_free to - * destroy it. Call it any sooner and the register windows - * go bye-bye. - */ - set _C_LABEL(idle_u), %l1 - sethi %hi(CPCB), %l6 -#if 0 - /* Get rid of the stack */ - rdpr %ver, %o0 - wrpr %g0, 0, %canrestore ! Fixup window state regs - and %o0, 0x0f, %o0 - wrpr %g0, 0, %otherwin - wrpr %g0, %o0, %cleanwin ! kernel don't care, but user does - dec 1, %o0 ! What happens if we don't subtract 2? - wrpr %g0, %o0, %cansave - flushw ! DEBUG -#endif /* 0 */ - - stx %l1, [%l6 + %lo(CPCB)] ! cpcb = &idle_u - set _C_LABEL(idle_u) + USPACE - CC64FSZ, %o0 ! set new %sp - sub %o0, BIAS, %sp ! Maybe this should be a save? - wrpr %g0, 0, %canrestore - wrpr %g0, 0, %otherwin - rdpr %ver, %l7 - and %l7, CWP, %l7 - wrpr %l7, 0, %cleanwin - dec 1, %l7 ! NWINDOWS-1-1 - wrpr %l7, %cansave - clr %fp ! End of stack. -#ifdef DEBUG - flushw ! DEBUG - set _C_LABEL(idle_u), %l6 - SET_SP_REDZONE %l6, %l5 -#endif /* DEBUG */ - wrpr %g0, PSTATE_INTR, %pstate ! and then enable traps - call _C_LABEL(exit2) ! exit2(p) - mov %l2, %o0 - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_lock_idle) ! Acquire sched_lock -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - wrpr %g0, PIL_SCHED, %pil ! Set splsched() - - /* - * Now fall through to `the last switch'. %g6 was set to - * %hi(cpcb), but may have been clobbered in kmem_free, - * so all the registers described below will be set here. - * - * Since the process has exited we can blow its context - * out of the MMUs now to free up those TLB entries rather - * than have more useful ones replaced. - * - * REGISTER USAGE AT THIS POINT: - * %l2 = %hi(_whichqs) - * %l4 = lastproc - * %l5 = oldpsr (excluding ipl bits) - * %l6 = %hi(cpcb) - * %l7 = %hi(curproc) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o3 = whichqs - */ - - INCR _C_LABEL(nswitchexit) ! nswitchexit++; - INCR _C_LABEL(uvmexp)+V_SWTCH ! cnt.v_switch++; - - mov CTX_SECONDARY, %o0 - sethi %hi(_C_LABEL(whichqs)), %l2 - sethi %hi(CPCB), %l6 - sethi %hi(CURPROC), %l7 - ldxa [%o0] ASI_DMMU, %l1 ! Don't demap the kernel - ldx [%l6 + %lo(CPCB)], %l5 - clr %l4 ! lastproc = NULL; - brz,pn %l1, 1f - set DEMAP_CTX_SECONDARY, %l1 ! Demap secondary context - stxa %g1, [%l1] ASI_DMMU_DEMAP - stxa %g1, [%l1] ASI_IMMU_DEMAP - membar #Sync -1: - stxa %g0, [%o0] ASI_DMMU ! Clear out our context - membar #Sync - /* FALLTHROUGH */ - -/* - * When no processes are on the runq, switch - * idles here waiting for something to come ready. - * The registers are set up as noted above. - */ - .globl idle -idle: -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_unlock_idle) ! Release sched_lock -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - stx %g0, [%l7 + %lo(CURPROC)] ! curproc = NULL; -1: ! spin reading _whichqs until nonzero - wrpr %g0, PSTATE_INTR, %pstate ! Make sure interrupts are enabled - wrpr %g0, 0, %pil ! (void) spl0(); - ld [%l2 + %lo(_C_LABEL(whichqs))], %o3 - brnz,pt %o3, notidle ! Something to run - nop -#ifdef UVM_PAGE_IDLE_ZERO - ! Check uvm.page_idle_zero - sethi %hi(_C_LABEL(uvm) + UVM_PAGE_IDLE_ZERO), %o3 - ld [%o3 + %lo(_C_LABEL(uvm) + UVM_PAGE_IDLE_ZERO)], %o3 - brz,pn %o3, 1b - nop - - ! zero some pages - call _C_LABEL(uvm_pageidlezero) - nop -#endif /* UVM_PAGE_IDLE_ZERO */ - ba,a,pt %xcc, 1b - nop ! spitfire bug -notidle: - wrpr %g0, PIL_SCHED, %pil ! (void) splhigh(); -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_lock_idle) ! Grab sched_lock - add %o7, (Lsw_scan-.-4), %o7 ! Return to Lsw_scan directly -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - ba,a,pt %xcc, Lsw_scan - nop ! spitfire bug - -Lsw_panic_rq: - sethi %hi(1f), %o0 - call _C_LABEL(panic) - or %lo(1f), %o0, %o0 Lsw_panic_wchan: - sethi %hi(2f), %o0 - call _C_LABEL(panic) - or %lo(2f), %o0, %o0 + sethi %hi(1f), %o0 + call _C_LABEL(panic) + or %lo(1f), %o0, %o0 Lsw_panic_srun: - sethi %hi(3f), %o0 - call _C_LABEL(panic) - or %lo(3f), %o0, %o0 - .data -1: .asciz "switch rq" -2: .asciz "switch wchan" -3: .asciz "switch SRUN" -idlemsg: .asciz "idle %x %x %x %x" -idlemsg1: .asciz " %x %x %x\r\n" - _ALIGN + sethi %hi(2f), %o0 + call _C_LABEL(panic) + or %lo(2f), %o0, %o0 + .data +1: .asciz "switch wchan" +2: .asciz "switch SRUN" + .text /* - * cpu_switch() picks a process to run and runs it, saving the current - * one away. On the assumption that (since most workstations are - * single user machines) the chances are quite good that the new - * process will turn out to be the current process, we defer saving - * it here until we have found someone to load. If that someone - * is the current process we avoid both store and load. + * cpu_switchto(struct proc *old, struct proc *new) * - * cpu_switch() is always entered at splstatclock or splhigh. - * - * IT MIGHT BE WORTH SAVING BEFORE ENTERING idle TO AVOID HAVING TO - * SAVE LATER WHEN SOMEONE ELSE IS READY ... MUST MEASURE! - * - * Apparently cpu_switch() is called with curproc as the first argument, - * but no port seems to make use of that parameter. + * Save the context of "old" and switch to "new". */ - .globl _C_LABEL(time) -ENTRY(cpu_switch) +ENTRY(cpu_switchto) save %sp, -CC64FSZ, %sp - /* - * REGISTER USAGE AT THIS POINT: - * %l1 = tmp 0 - * %l2 = %hi(_C_LABEL(whichqs)) - * %l3 = p - * %l4 = lastproc - * %l5 = cpcb - * %l6 = %hi(CPCB) - * %l7 = %hi(CURPROC) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4, then at Lsw_scan, whichqs - * %o4 = tmp 5, then at Lsw_scan, which - * %o5 = tmp 6, then at Lsw_scan, q - */ -#ifdef DEBUG - set swdebug, %o1 - ld [%o1], %o1 - brz,pt %o1, 2f - set 1f, %o0 - call printf - nop - .data -1: .asciz "s" - _ALIGN - .globl swdebug -swdebug: .word 0 - .text -2: -#endif /* DEBUG */ flushw ! We don't have anything else to run, so why not flush -#ifdef DEBUG - save %sp, -CC64FSZ, %sp - flushw - restore -#endif /* DEBUG */ rdpr %pstate, %o1 ! oldpstate = %pstate; wrpr %g0, PSTATE_INTR, %pstate ! make sure we're on normal globals + + mov %i0, %l4 ! oldproc + mov %i1, %l3 ! newproc + sethi %hi(CPCB), %l6 - sethi %hi(_C_LABEL(whichqs)), %l2 ! set up addr regs ldx [%l6 + %lo(CPCB)], %l5 - sethi %hi(CURPROC), %l7 + sethi %hi(CURPROC), %l7 stx %o7, [%l5 + PCB_PC] ! cpcb->pcb_pc = pc; - ldx [%l7 + %lo(CURPROC)], %l4 ! lastproc = curproc; sth %o1, [%l5 + PCB_PSTATE] ! cpcb->pcb_pstate = oldpstate; - stx %g0, [%l7 + %lo(CURPROC)] ! curproc = NULL; - -Lsw_scan: - ld [%l2 + %lo(_C_LABEL(whichqs))], %o3 - -#ifndef POPC - .globl _C_LABEL(__ffstab) - /* - * Optimized inline expansion of `which = ffs(whichqs) - 1'; - * branches to idle if ffs(whichqs) was 0. - */ - set _C_LABEL(__ffstab), %o2 - andcc %o3, 0xff, %o1 ! byte 0 zero? - bz,a,pn %icc, 1f ! yes, try byte 1 - srl %o3, 8, %o0 - ba,pt %icc, 2f ! ffs = ffstab[byte0]; which = ffs - 1; - ldsb [%o2 + %o1], %o0 -1: andcc %o0, 0xff, %o1 ! byte 1 zero? - bz,a,pn %icc, 1f ! yes, try byte 2 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte1] + 7; - ba,pt %icc, 3f - add %o0, 7, %o4 -1: andcc %o0, 0xff, %o1 ! byte 2 zero? - bz,a,pn %icc, 1f ! yes, try byte 3 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte2] + 15; - ba,pt %icc, 3f - add %o0, 15, %o4 -1: ldsb [%o2 + %o0], %o0 ! ffs = ffstab[byte3] + 24 - addcc %o0, 24, %o0 ! (note that ffstab[0] == -24) - bz,pn %icc, idle ! if answer was 0, go idle -! XXX check no delay slot -2: sub %o0, 1, %o4 -3: /* end optimized inline expansion */ - -#else /* POPC */ - /* - * Optimized inline expansion of `which = ffs(whichqs) - 1'; - * branches to idle if ffs(whichqs) was 0. - * - * This version uses popc. - * - * XXXX spitfires and blackbirds don't implement popc. - * - */ - brz,pn %o3, idle ! Don't bother if queues are empty - neg %o3, %o1 ! %o1 = -zz - xnor %o3, %o1, %o2 ! %o2 = zz ^ ~ -zz - popc %o2, %o4 ! which = popc(whichqs) - dec %o4 ! which = ffs(whichqs) - 1 - -#endif /* POPC */ - /* - * We found a nonempty run queue. Take its first process. - */ - set _C_LABEL(qs), %o5 ! q = &qs[which]; - sll %o4, 3+1, %o0 - add %o0, %o5, %o5 - ldx [%o5], %l3 ! p = q->ph_link; - cmp %l3, %o5 ! if (p == q) - be,pn %icc, Lsw_panic_rq ! panic("switch rq"); -! XXX check no delay slot - ldx [%l3], %o0 ! tmp0 = p->p_forw; - stx %o0, [%o5] ! q->ph_link = tmp0; - stx %o5, [%o0 + 8] ! tmp0->p_back = q; - cmp %o0, %o5 ! if (tmp0 == q) - bne 1f -! XXX check no delay slot - mov 1, %o1 ! whichqs &= ~(1 << which); - sll %o1, %o4, %o1 - andn %o3, %o1, %o3 - st %o3, [%l2 + %lo(_C_LABEL(whichqs))] -1: /* * PHASE TWO: NEW REGISTER USAGE: * %l1 = newpcb @@ -5945,7 +5634,6 @@ Lsw_scan: /* * Committed to running process p. - * It may be the same as the one we were running before. */ #if defined(MULTIPROCESSOR) /* @@ -5958,19 +5646,7 @@ Lsw_scan: sethi %hi(CPUINFO_VA+CI_WANT_RESCHED), %o0 st %g0, [%o0 + %lo(CPUINFO_VA+CI_WANT_RESCHED)] ! want_resched = 0; ldx [%l3 + P_ADDR], %l1 ! newpcb = p->p_addr; - stx %g0, [%l3 + 8] ! p->p_back = NULL; -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - /* - * Done mucking with the run queues, release the - * scheduler lock, but keep interrupts out. - */ - call _C_LABEL(sched_unlock_idle) -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - stx %l4, [%l7 + %lo(CURPROC)] ! restore old proc so we can save it - - cmp %l3, %l4 ! p == lastproc? - be,pt %xcc, Lsw_sameproc ! yes, go return 0 - nop + stx %l4, [%l7 + %lo(CURPROC)] ! restore old proc so we can save it /* * Not the old process. Save the old process, if any; @@ -5980,7 +5656,6 @@ Lsw_scan: brz,pn %l4, Lsw_load ! if no old process, go load wrpr %g0, PSTATE_KERN, %pstate - INCR _C_LABEL(nswitchdiff) ! clobbers %o0,%o1,%o2 wb1: flushw ! save all register windows except this one stx %i7, [%l5 + PCB_PC] ! Save rpc @@ -6060,11 +5735,6 @@ Lsw_havectx: membar #Sync ! Maybe we should use flush here? flush %sp -Lsw_sameproc: - /* - * We are resuming the process that was running at the - * call to switch(). Just set psr ipl and return. - */ ! wrpr %g0, 0, %cleanwin ! DEBUG clr %g4 ! This needs to point to the base of the data segment wr %g0, ASI_PRIMARY_NOFAULT, %asi ! Restore default ASI @@ -6072,6 +5742,18 @@ Lsw_sameproc: ret restore +ENTRY(cpu_idle_enter) + retl + nop + +ENTRY(cpu_idle_cycle) + retl + nop + +ENTRY(cpu_idle_leave) + retl + nop + /* * Snapshot the current process so that stack frames are up to date. * Only used just before a crash dump. diff --git a/sys/arch/sparc64/sparc64/vm_machdep.c b/sys/arch/sparc64/sparc64/vm_machdep.c index 5d46c9eb715..88ba247878a 100644 --- a/sys/arch/sparc64/sparc64/vm_machdep.c +++ b/sys/arch/sparc64/sparc64/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.15 2007/06/20 17:29:36 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.16 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.38 2001/06/30 00:02:20 eeh Exp $ */ /* @@ -316,8 +316,7 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) * run. */ void -cpu_exit(p) - struct proc *p; +cpu_exit(struct proc *p) { register struct fpstate64 *fs; @@ -328,8 +327,9 @@ cpu_exit(p) } free((void *)fs, M_SUBPROC); } - switchexit(p); - /* NOTREACHED */ + + pmap_deactivate(p); + sched_exit(p); } /* diff --git a/sys/arch/vax/include/cpu.h b/sys/arch/vax/include/cpu.h index 80b05d5d185..dc6ec203a16 100644 --- a/sys/arch/vax/include/cpu.h +++ b/sys/arch/vax/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.25 2007/05/16 05:19:13 miod Exp $ */ +/* $OpenBSD: cpu.h,v 1.26 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: cpu.h,v 1.41 1999/10/21 20:01:36 ragge Exp $ */ /* @@ -129,6 +129,10 @@ extern int want_resched; /* resched() was called */ */ #define need_proftick(p) mtpr(AST_OK,PR_ASTLVL) +#define cpu_idle_enter() do { /* nothing */ } while (0) +#define cpu_idle_cycle() do { /* nothing */ } while (0) +#define cpu_idle_leave() do { /* nothing */ } while (0) + /* * This defines the I/O device register space size in pages. */ diff --git a/sys/arch/vax/include/macros.h b/sys/arch/vax/include/macros.h index 0c514ff5aa7..87bd942c43a 100644 --- a/sys/arch/vax/include/macros.h +++ b/sys/arch/vax/include/macros.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macros.h,v 1.14 2006/11/06 21:31:36 miod Exp $ */ +/* $OpenBSD: macros.h,v 1.15 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: macros.h,v 1.20 2000/07/19 01:02:52 matt Exp $ */ /* @@ -232,15 +232,10 @@ skpc(int mask, size_t size, u_char *cp) return ret; } -#define setrunqueue(p) \ - __asm__ __volatile("movl %0,r0;jsb Setrq":: "g"(p):"r0","r1","r2"); - -#define remrunqueue(p) \ - __asm__ __volatile("movl %0,r0;jsb Remrq":: "g"(p):"r0","r1","r2"); - -#define cpu_switch(p) \ - __asm__ __volatile("movl %0,r0;movpsl -(sp);jsb Swtch" \ - ::"g"(p):"r0","r1","r2","r3"); +#define cpu_switchto(o, n) \ + __asm__ __volatile__( \ + "movl %0,r0; movl %1, r1; movpsl -(sp); jsb __cpu_switchto" \ + :: "g"(o), "g"(n) : "r0", "r1"); /* * Interlock instructions. Used both in multiprocessor environments to diff --git a/sys/arch/vax/vax/subr.s b/sys/arch/vax/vax/subr.s index 6c669bd47af..b0ca031e3d2 100644 --- a/sys/arch/vax/vax/subr.s +++ b/sys/arch/vax/vax/subr.s @@ -1,4 +1,4 @@ -/* $OpenBSD: subr.s,v 1.26 2007/05/16 05:19:15 miod Exp $ */ +/* $OpenBSD: subr.s,v 1.27 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: subr.s,v 1.32 1999/03/25 00:41:48 mrg Exp $ */ /* @@ -240,114 +240,37 @@ ENTRY(longjmp, 0) #endif # -# setrunqueue/remrunqueue fast variants. +# void +# cpu_switchto(struct proc *oldproc = r0, struct proc *newproc = r1); # -JSBENTRY(Setrq) -#ifdef DIAGNOSTIC - tstl 4(r0) # Check that process actually are off the queue - beql 1f - pushab setrq - calls $1,_panic -setrq: .asciz "setrunqueue" -#endif -1: extzv $2,$6,P_PRIORITY(r0),r1 # get priority - movaq _qs[r1],r2 # get address of queue - insque (r0),*4(r2) # put proc last in queue - bbss r1,_whichqs,1f # set queue bit. -1: rsb - -JSBENTRY(Remrq) - extzv $2,$6,P_PRIORITY(r0),r1 -#ifdef DIAGNOSTIC - bbs r1,_whichqs,1f - pushab remrq - calls $1,_panic -remrq: .asciz "remrunqueue" -#endif -1: remque (r0),r2 - bneq 1f # Not last process on queue - bbsc r1,_whichqs,1f -1: clrl 4(r0) # saftey belt - rsb - -# -# Idle loop. Here we could do something fun, maybe, like calculating -# pi or something. -# -idle: mtpr $0,$PR_IPL # Enable all types of interrupts -1: tstl _whichqs # Anything ready to run? - beql 1b # no, continue to loop - brb Swtch # Yes, goto switch again. +#define CURPROC _cpu_info_store + CI_CURPROC -# -# cpu_switch, cpu_exit and the idle loop implemented in assembler -# for efficiency. r0 contains pointer to last process. -# +JSBENTRY(__cpu_switchto) + svpctx -#define CURPROC _cpu_info_store + CI_CURPROC + movb $SONPROC,P_STAT(r1) # p->p_stat = SONPROC + movl r1, CURPROC # set new process running -JSBENTRY(Swtch) - clrl CURPROC # Stop process accounting -#bpt - mtpr $0x1f,$PR_IPL # block all interrupts - ffs $0,$32,_whichqs,r3 # Search for bit set - beql idle # no bit set, go to idle loop - - movaq _qs[r3],r1 # get address of queue head - remque *(r1),r2 # remove proc pointed to by queue head -#ifdef DIAGNOSTIC - bvc 1f # check if something on queue - pushab noque - calls $1,_panic -noque: .asciz "swtch" -#endif -1: bneq 2f # more processes on queue? - bbsc r3,_whichqs,2f # no, clear bit in whichqs -2: clrl 4(r2) # clear proc backpointer - clrl _want_resched # we are now changing process - movb $SONPROC,P_STAT(r2) # p->p_stat = SONPROC - movl r2,CURPROC # set new process running - cmpl r0,r2 # Same process? - bneq 1f # No, continue - rsb -xxd: -1: movl P_ADDR(r2),r0 # Get pointer to new pcb. + movl P_ADDR(r1),r0 # Get pointer to new pcb. addl3 r0,$IFTRAP,pcbtrap # Save for copy* functions. -# -# Nice routine to get physical from virtual addresses. -# + # inline kvtophys extzv $9,$21,r0,r1 # extract offset movl *_Sysmap[r1],r2 # get pte ashl $9,r2,r3 # shift to get phys address. # # Do the actual process switch. pc + psl are already on stack, from -# the calling routine. +# the beginning of this routine. # - svpctx mtpr r3,$PR_PCBB - ldpctx - rei - -# -# the last routine called by a process. -# - -ENTRY(cpu_exit,0) - movl 4(ap),r6 # Process pointer in r6 - mtpr $0x18,$PR_IPL # Block almost everything - addl3 $512,_scratch,sp # Change stack, and schedule it to be freed - pushl r6 - calls $1,_exit2 - - clrl r0 # No process to switch from - bicl3 $0xc0000000,_scratch,r1 - mtpr r1,$PR_PCBB - brw Swtch + pushl CURPROC + calls $1, _C_LABEL(pmap_activate) + ldpctx + rei # # copy/fetch/store routines. diff --git a/sys/arch/vax/vax/vm_machdep.c b/sys/arch/vax/vax/vm_machdep.c index 7205101225d..603bb17e3d3 100644 --- a/sys/arch/vax/vax/vm_machdep.c +++ b/sys/arch/vax/vax/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.34 2007/06/20 17:29:36 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.35 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.67 2000/06/29 07:14:34 mrg Exp $ */ /* @@ -58,6 +58,16 @@ #include <sys/syscallargs.h> +void +cpu_exit(struct proc *p) +{ + int s; + s = splhigh(); /* splclock(); */ + + pmap_deactivate(p); + sched_exit(p); +} + /* * Finish a fork operation, with process p2 nearly set up. * Copy and update the pcb and trap frame, making the child ready to run. @@ -110,13 +120,6 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) p2->p_addr->u_pcb.framep = tf; bcopy(p1->p_addr->u_pcb.framep, tf, sizeof(*tf)); - /* - * Activate address space for the new process. The PTEs have - * already been allocated by way of pmap_create(). - * This writes the page table registers to the PCB. - */ - pmap_activate(p2); - /* Mark guard page invalid in kernel stack */ *kvtopte((u_int)p2->p_addr + REDZONEADDR) &= ~PG_V; diff --git a/sys/conf/files b/sys/conf/files index 2ab1b985dde..8487299b53d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.410 2007/09/12 12:59:55 mglocker Exp $ +# $OpenBSD: files,v 1.411 2007/10/10 15:53:53 art Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -645,6 +645,7 @@ file kern/kern_physio.c file kern/kern_proc.c file kern/kern_prot.c file kern/kern_resource.c +file kern/kern_sched.c file kern/kern_sensors.c !small_kernel file kern/kern_sig.c file kern/kern_subr.c diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index e3047847f8f..98c75f5e618 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.144 2007/09/10 18:49:45 miod Exp $ */ +/* $OpenBSD: init_main.c,v 1.145 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -327,7 +327,9 @@ main(void *framep) (void)chgproccnt(0, 1); /* Initialize run queues */ - rqinit(); + sched_init_runqueues(); + sleep_queue_init(); + sched_init_cpu(curcpu()); /* Initialize work queues */ workq_init(); diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index f4e18101952..27c7bb79b74 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_clock.c,v 1.64 2007/05/16 17:27:30 art Exp $ */ +/* $OpenBSD: kern_clock.c,v 1.65 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $ */ /*- @@ -546,7 +546,7 @@ statclock(struct clockframe *frame) if (p != NULL) p->p_iticks++; spc->spc_cp_time[CP_INTR]++; - } else if (p != NULL) { + } else if (p != NULL && p != spc->spc_idleproc) { p->p_sticks++; spc->spc_cp_time[CP_SYS]++; } else diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 4c85dd84543..fa68a37f72a 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.71 2007/04/12 22:14:15 tedu Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.72 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -315,16 +315,8 @@ exit1(struct proc *p, int rv, int flags) sigactsfree(p); /* - * Clear curproc after we've done all operations - * that could block, and before tearing down the rest - * of the process state that might be used from clock, etc. - * Also, can't clear curproc while we're still runnable, - * as we're not on a run queue (we are current, just not - * a proper proc any longer!). - * - * Other substructures are freed from wait(). + * Other substructures are freed from reaper and wait(). */ - curproc = NULL; /* * If emulation has process exit hook, call it now. @@ -373,15 +365,11 @@ struct proclist deadproc = LIST_HEAD_INITIALIZER(deadproc); void exit2(struct proc *p) { - int s; - mtx_enter(&deadproc_mutex); LIST_INSERT_HEAD(&deadproc, p, p_hash); mtx_leave(&deadproc_mutex); wakeup(&deadproc); - - SCHED_LOCK(s); } /* @@ -396,6 +384,8 @@ reaper(void) KERNEL_PROC_UNLOCK(curproc); + SCHED_ASSERT_UNLOCKED(); + for (;;) { mtx_enter(&deadproc_mutex); p = LIST_FIRST(&deadproc); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index d54932106d7..8a048fd5f65 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.92 2007/07/25 23:11:52 art Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.93 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -224,7 +224,6 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, p2->p_stat = SIDL; /* protect against others */ p2->p_exitsig = exitsig; - p2->p_forw = p2->p_back = NULL; #ifdef RTHREADS if (flags & FORK_THREAD) { @@ -501,7 +500,12 @@ proc_trampoline_mp(void) p = curproc; + SCHED_ASSERT_LOCKED(); + __mp_unlock(&sched_lock); + spl0(); SCHED_ASSERT_UNLOCKED(); + KASSERT(__mp_lock_held(&kernel_lock) == 0); + KERNEL_PROC_LOCK(p); } #endif diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index ef16630f108..66d8a8bb5ac 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_proc.c,v 1.35 2007/09/07 15:00:20 art Exp $ */ +/* $OpenBSD: kern_proc.c,v 1.36 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* @@ -377,8 +377,8 @@ proc_printit(struct proc *p, const char *modif, int (*pr)(const char *, ...)) p->p_comm, p->p_pid, pst, p->p_flag, P_BITS); (*pr)(" pri=%u, usrpri=%u, nice=%d\n", p->p_priority, p->p_usrpri, p->p_nice); - (*pr)(" forw=%p, back=%p, list=%p,%p\n", - p->p_forw, p->p_back, p->p_list.le_next, p->p_list.le_prev); + (*pr)(" forw=%p, list=%p,%p\n", + TAILQ_NEXT(p, p_runq), p->p_list.le_next, p->p_list.le_prev); (*pr)(" user=%p, vmspace=%p\n", p->p_addr, p->p_vmspace); (*pr)(" estcpu=%u, cpticks=%d, pctcpu=%u.%u%, swtime=%u\n", diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c new file mode 100644 index 00000000000..83c7240c739 --- /dev/null +++ b/sys/kern/kern_sched.c @@ -0,0 +1,242 @@ +/* $OpenBSD: kern_sched.c,v 1.1 2007/10/10 15:53:53 art Exp $ */ +/* + * Copyright (c) 2007 Artur Grabowski <art@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> + +#include <sys/sched.h> +#include <sys/proc.h> +#include <sys/kthread.h> +#include <sys/systm.h> +#include <sys/resourcevar.h> +#include <sys/signalvar.h> +#include <sys/mutex.h> + +#include <uvm/uvm_extern.h> + +struct proc *sched_chooseproc(void); +void sched_kthreads_create(void *); +void sched_idle(void *); + +/* + * A few notes about cpu_switchto that is implemented in MD code. + * + * cpu_switchto takes two arguments, the old proc and the proc + * it should switch to. The new proc will never be NULL, so we always have + * a saved state that we need to switch to. The old proc however can + * be NULL if the process is exiting. NULL for the old proc simply + * means "don't bother saving old state". + * + * cpu_switchto is supposed to atomically load the new state of the process + * including the pcb, pmap and setting curproc, the p_cpu pointer in the + * proc and p_stat to SONPROC. Atomically with respect to interrupts, other + * cpus in the system must not depend on this state being consistent. + * Therefore no locking is necessary in cpu_switchto other than blocking + * interrupts during the context switch. + */ + +/* + * sched_init_cpu is called from main() for the boot cpu, then it's the + * responsibility of the MD code to call it for all other cpus. + */ +void +sched_init_cpu(struct cpu_info *ci) +{ + struct schedstate_percpu *spc = &ci->ci_schedstate; + + spc->spc_idleproc = NULL; + + kthread_create_deferred(sched_kthreads_create, ci); + + LIST_INIT(&spc->spc_deadproc); +} + +void +sched_kthreads_create(void *v) +{ + struct cpu_info *ci = v; + struct schedstate_percpu *spc = &ci->ci_schedstate; + static int num; + + if (kthread_create(sched_idle, ci, &spc->spc_idleproc, "idle%d", num)) + panic("fork idle"); + + num++; +} + +void +sched_idle(void *v) +{ + struct proc *p = curproc; + struct cpu_info *ci = v; + int s; + + KERNEL_PROC_UNLOCK(p); + + /* + * First time we enter here, we're not supposed to idle, + * just go away for a while. + */ + SCHED_LOCK(s); + p->p_stat = SSLEEP; + mi_switch(); + SCHED_UNLOCK(s); + + while (1) { + KASSERT(ci == curcpu()); + KASSERT(curproc == ci->ci_schedstate.spc_idleproc); + + while (!sched_is_idle()) { + struct schedstate_percpu *spc = &ci->ci_schedstate; + struct proc *dead; + + SCHED_LOCK(s); + p->p_stat = SSLEEP; + mi_switch(); + SCHED_UNLOCK(s); + + while ((dead = LIST_FIRST(&spc->spc_deadproc))) { + LIST_REMOVE(dead, p_hash); + exit2(dead); + } + } + + cpu_idle_enter(); + while (sched_is_idle()) + cpu_idle_cycle(); + cpu_idle_leave(); + } +} + +/* + * To free our address space we have to jump through a few hoops. + * The freeing is done by the reaper, but until we have one reaper + * per cpu, we have no way of putting this proc on the deadproc list + * and waking up the reaper without risking having our address space and + * stack torn from under us before we manage to switch to another proc. + * Therefore we have a per-cpu list of dead processes where we put this + * proc and have idle clean up that list and move it to the reaper list. + * All this will be unnecessary once we can bind the reaper this cpu + * and not risk having it switch to another in case it sleeps. + */ +void +sched_exit(struct proc *p) +{ + struct schedstate_percpu *spc = &curcpu()->ci_schedstate; + struct timeval tv; + struct proc *idle; + int s; + + microuptime(&tv); + timersub(&tv, &spc->spc_runtime, &tv); + timeradd(&p->p_rtime, &tv, &p->p_rtime); + + LIST_INSERT_HEAD(&spc->spc_deadproc, p, p_hash); + +#ifdef MULTIPROCESSOR + KASSERT(__mp_lock_held(&kernel_lock) == 0); +#endif + + SCHED_LOCK(s); + idle = spc->spc_idleproc; + idle->p_stat = SRUN; + cpu_switchto(NULL, idle); +} + +/* + * Run queue management. + * + * The run queue management is just like before, except that it's with + * a bit more modern queue handling. + */ + +TAILQ_HEAD(prochead, proc) sched_qs[NQS]; +volatile int sched_whichqs; + +void +sched_init_runqueues(void) +{ + int i; + + for (i = 0; i < NQS; i++) + TAILQ_INIT(&sched_qs[i]); + +#ifdef MULTIPROCESSOR + SIMPLE_LOCK_INIT(&sched_lock); +#endif +} + +void +setrunqueue(struct proc *p) +{ + int queue = p->p_priority >> 2; + + SCHED_ASSERT_LOCKED(); + + TAILQ_INSERT_TAIL(&sched_qs[queue], p, p_runq); + sched_whichqs |= (1 << queue); +} + +void +remrunqueue(struct proc *p) +{ + int queue = p->p_priority >> 2; + + SCHED_ASSERT_LOCKED(); + + TAILQ_REMOVE(&sched_qs[queue], p, p_runq); + if (TAILQ_EMPTY(&sched_qs[queue])) + sched_whichqs &= ~(1 << queue); +} + +struct proc * +sched_chooseproc(void) +{ + struct proc *p; + int queue; + + SCHED_ASSERT_LOCKED(); + +again: + if (sched_whichqs == 0) { + p = curcpu()->ci_schedstate.spc_idleproc; + if (p == NULL) { + int s; + /* + * We get here if someone decides to switch during + * boot before forking kthreads, bleh. + * This is kind of like a stupid idle loop. + */ +#ifdef MULTIPROCESSOR + __mp_unlock(&sched_lock); +#endif + spl0(); + delay(10); + SCHED_LOCK(s); + goto again; + } + KASSERT(p); + p->p_stat = SRUN; + } else { + queue = ffs(sched_whichqs) - 1; + p = TAILQ_FIRST(&sched_qs[queue]); + TAILQ_REMOVE(&sched_qs[queue], p, p_runq); + if (TAILQ_EMPTY(&sched_qs[queue])) + sched_whichqs &= ~(1 << queue); + } + + return (p); +} diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 849dffefc57..8cd4a4285e1 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_synch.c,v 1.80 2007/05/16 17:27:30 art Exp $ */ +/* $OpenBSD: kern_synch.c,v 1.81 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /* @@ -67,10 +67,17 @@ void endtsleep(void *); */ #define TABLESIZE 128 #define LOOKUP(x) (((long)(x) >> 8) & (TABLESIZE - 1)) -struct slpque { - struct proc *sq_head; - struct proc **sq_tailp; -} slpque[TABLESIZE]; +TAILQ_HEAD(slpque,proc) slpque[TABLESIZE]; + +void +sleep_queue_init(void) +{ + int i; + + for (i = 0; i < TABLESIZE; i++) + TAILQ_INIT(&slpque[i]); +} + /* * During autoconfiguration or after a panic, a sleep will simply @@ -133,15 +140,12 @@ void sleep_setup(struct sleep_state *sls, void *ident, int prio, const char *wmesg) { struct proc *p = curproc; - struct slpque *qp; #ifdef DIAGNOSTIC if (ident == NULL) panic("tsleep: no ident"); if (p->p_stat != SONPROC) panic("tsleep: not SONPROC"); - if (p->p_back != NULL) - panic("tsleep: p_back not NULL"); #endif #ifdef KTRACE @@ -159,12 +163,7 @@ sleep_setup(struct sleep_state *sls, void *ident, int prio, const char *wmesg) p->p_wmesg = wmesg; p->p_slptime = 0; p->p_priority = prio & PRIMASK; - qp = &slpque[LOOKUP(ident)]; - if (qp->sq_head == 0) - qp->sq_head = p; - else - *qp->sq_tailp = p; - *(qp->sq_tailp = &p->p_forw) = NULL; + TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_runq); } void @@ -179,11 +178,12 @@ sleep_finish(struct sleep_state *sls, int do_sleep) mi_switch(); } else if (!do_sleep) { unsleep(p); + } + #ifdef DIAGNOSTIC - if (p->p_stat != SONPROC) - panic("sleep_finish !SONPROC"); + if (p->p_stat != SONPROC) + panic("sleep_finish !SONPROC"); #endif - } p->p_cpu->ci_schedstate.spc_curpriority = p->p_usrpri; SCHED_UNLOCK(sls->sls_s); @@ -296,17 +296,9 @@ endtsleep(void *arg) void unsleep(struct proc *p) { - struct slpque *qp; - struct proc **hp; - if (p->p_wchan) { - hp = &(qp = &slpque[LOOKUP(p->p_wchan)])->sq_head; - while (*hp != p) - hp = &(*hp)->p_forw; - *hp = p->p_forw; - if (qp->sq_tailp == &p->p_forw) - qp->sq_tailp = hp; - p->p_wchan = 0; + TAILQ_REMOVE(&slpque[LOOKUP(p->p_wchan)], p, p_runq); + p->p_wchan = NULL; } } @@ -317,25 +309,22 @@ void wakeup_n(void *ident, int n) { struct slpque *qp; - struct proc *p, **q; + struct proc *p; + struct proc *pnext; int s; SCHED_LOCK(s); qp = &slpque[LOOKUP(ident)]; -restart: - for (q = &qp->sq_head; (p = *q) != NULL; ) { + for (p = TAILQ_FIRST(qp); p != NULL && n != 0; p = pnext) { + pnext = TAILQ_NEXT(p, p_runq); #ifdef DIAGNOSTIC - if (p->p_back) - panic("wakeup: p_back not NULL"); if (p->p_stat != SSLEEP && p->p_stat != SSTOP) panic("wakeup: p_stat is %d", (int)p->p_stat); #endif if (p->p_wchan == ident) { --n; p->p_wchan = 0; - *q = p->p_forw; - if (qp->sq_tailp == &p->p_forw) - qp->sq_tailp = q; + TAILQ_REMOVE(qp, p, p_runq); if (p->p_stat == SSLEEP) { /* OPTIMIZED EXPANSION OF setrunnable(p); */ if (p->p_slptime > 1) @@ -357,13 +346,8 @@ restart: need_resched(p->p_cpu); /* END INLINE EXPANSION */ - if (n != 0) - goto restart; - else - break; } - } else - q = &p->p_forw; + } } SCHED_UNLOCK(s); } diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index bdc9d6850a2..c9b12d50fab 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.157 2007/09/07 15:00:20 art Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.158 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -1280,9 +1280,7 @@ fill_kproc2(struct proc *p, struct kinfo_proc2 *ki) ki->p_vm_tsize = vm->vm_tsize; ki->p_vm_dsize = vm->vm_dused; ki->p_vm_ssize = vm->vm_ssize; - - ki->p_forw = PTRTOINT64(p->p_forw); - ki->p_back = PTRTOINT64(p->p_back); + ki->p_forw = ki->p_back = 0; ki->p_addr = PTRTOINT64(p->p_addr); ki->p_stat = p->p_stat; ki->p_swtime = p->p_swtime; diff --git a/sys/kern/sched_bsd.c b/sys/kern/sched_bsd.c index 047207b1d39..aafcbb9eeb4 100644 --- a/sys/kern/sched_bsd.c +++ b/sys/kern/sched_bsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sched_bsd.c,v 1.12 2007/05/18 16:10:15 art Exp $ */ +/* $OpenBSD: sched_bsd.c,v 1.13 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /*- @@ -57,9 +57,6 @@ int lbolt; /* once a second sleep address */ int rrticks_init; /* # of hardclock ticks per roundrobin() */ -int whichqs; /* Bit mask summary of non-empty Q's. */ -struct prochd qs[NQS]; - struct SIMPLELOCK sched_lock; void scheduler_start(void); @@ -359,29 +356,26 @@ preempt(struct proc *newp) SCHED_UNLOCK(s); } - -/* - * Must be called at splstatclock() or higher. - */ void mi_switch(void) { - struct proc *p = curproc; /* XXX */ + struct schedstate_percpu *spc = &curcpu()->ci_schedstate; + struct proc *p = curproc; + struct proc *nextproc; struct rlimit *rlim; struct timeval tv; -#if defined(MULTIPROCESSOR) +#ifdef MULTIPROCESSOR int hold_count; int sched_count; #endif - struct schedstate_percpu *spc = &p->p_cpu->ci_schedstate; + + KASSERT(p->p_stat != SONPROC); SCHED_ASSERT_LOCKED(); -#if defined(MULTIPROCESSOR) +#ifdef MULTIPROCESSOR /* * Release the kernel_lock, as we are about to yield the CPU. - * The scheduler lock is still held until cpu_switch() - * selects a new process and removes it from the run queue. */ sched_count = __mp_release_all_but_one(&sched_lock); if (p->p_flag & P_BIGLOCK) @@ -391,7 +385,6 @@ mi_switch(void) /* * Compute the amount of time during which the current * process was running, and add that to its total so far. - * XXX - use microuptime here to avoid strangeness. */ microuptime(&tv); if (timercmp(&tv, &spc->spc_runtime, <)) { @@ -427,16 +420,27 @@ mi_switch(void) */ spc->spc_schedflags &= ~SPCF_SWITCHCLEAR; - /* - * Pick a new current process and record its start time. - */ - uvmexp.swtch++; - cpu_switch(p); + nextproc = sched_chooseproc(); + + if (p != nextproc) { + uvmexp.swtch++; + cpu_switchto(p, nextproc); + } else { + p->p_stat = SONPROC; + } + + SCHED_ASSERT_LOCKED(); /* - * Make sure that MD code released the scheduler lock before - * resuming us. + * To preserve lock ordering, we need to release the sched lock + * and grab it after we grab the big lock. + * In the future, when the sched lock isn't recursive, we'll + * just release it here. */ +#ifdef MULTIPROCESSOR + __mp_unlock(&sched_lock); +#endif + SCHED_ASSERT_UNLOCKED(); /* @@ -444,11 +448,11 @@ mi_switch(void) * be running on a new CPU now, so don't use the cache'd * schedstate_percpu pointer. */ - KDASSERT(p->p_cpu != NULL); - KDASSERT(p->p_cpu == curcpu()); + KASSERT(p->p_cpu == curcpu()); + microuptime(&p->p_cpu->ci_schedstate.spc_runtime); -#if defined(MULTIPROCESSOR) +#ifdef MULTIPROCESSOR /* * Reacquire the kernel_lock now. We do this after we've * released the scheduler lock to avoid deadlock, and before @@ -460,20 +464,6 @@ mi_switch(void) #endif } -/* - * Initialize the (doubly-linked) run queues - * to be empty. - */ -void -rqinit(void) -{ - int i; - - for (i = 0; i < NQS; i++) - qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i]; - SIMPLE_LOCK_INIT(&sched_lock); -} - static __inline void resched_proc(struct proc *p, u_char pri) { diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 125978d8a74..a4d4a12fa62 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.100 2007/07/25 23:11:53 art Exp $ */ +/* $OpenBSD: proc.h,v 1.101 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -148,8 +148,7 @@ struct process; #endif struct proc { - struct proc *p_forw; /* Doubly-linked run/sleep queue. */ - struct proc *p_back; + TAILQ_ENTRY(proc) p_runq; LIST_ENTRY(proc) p_list; /* List of all processes. */ struct process *p_p; /* The process of this thread. */ @@ -401,14 +400,6 @@ extern struct pool ucred_pool; /* memory pool for ucreds */ extern struct pool session_pool; /* memory pool for sessions */ extern struct pool pcred_pool; /* memory pool for pcreds */ -#define NQS 32 /* 32 run queues. */ -extern int whichqs; /* Bit mask summary of non-empty Q's. */ -struct prochd { - struct proc *ph_link; /* Linked list of running processes. */ - struct proc *ph_rlink; -}; -extern struct prochd qs[NQS]; - struct simplelock; struct proc *pfind(pid_t); /* Find process by id. */ @@ -423,17 +414,10 @@ int inferior(struct proc *p); int leavepgrp(struct proc *p); void yield(void); void preempt(struct proc *); -void mi_switch(void); void pgdelete(struct pgrp *pgrp); void procinit(void); -#if !defined(remrunqueue) -void remrunqueue(struct proc *); -#endif void resetpriority(struct proc *); void setrunnable(struct proc *); -#if !defined(setrunqueue) -void setrunqueue(struct proc *); -#endif void unsleep(struct proc *); void wakeup_n(void *chan, int); void wakeup(void *chan); @@ -441,17 +425,13 @@ void wakeup(void *chan); void reaper(void); void exit1(struct proc *, int, int); void exit2(struct proc *); +void cpu_exit(struct proc *); int fork1(struct proc *, int, int, void *, size_t, void (*)(void *), void *, register_t *, struct proc **); -void rqinit(void); int groupmember(gid_t, struct ucred *); -#if !defined(cpu_switch) -void cpu_switch(struct proc *); -#endif #if !defined(cpu_wait) void cpu_wait(struct proc *); #endif -void cpu_exit(struct proc *); void child_return(void *); @@ -471,6 +451,7 @@ void sleep_setup_signal(struct sleep_state *, int); void sleep_finish(struct sleep_state *, int); int sleep_finish_timeout(struct sleep_state *); int sleep_finish_signal(struct sleep_state *); +void sleep_queue_init(void); int tsleep(void *, int, const char *, int); #define ltsleep(c, p, w, t, l) tsleep(c, p, w, t) diff --git a/sys/sys/sched.h b/sys/sys/sched.h index 407ec09f651..62b7f568637 100644 --- a/sys/sys/sched.h +++ b/sys/sys/sched.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sched.h,v 1.16 2007/05/18 14:41:55 art Exp $ */ +/* $OpenBSD: sched.h,v 1.17 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: sched.h,v 1.2 1999/02/28 18:14:58 ross Exp $ */ /*- @@ -76,6 +76,8 @@ #ifndef _SYS_SCHED_H_ #define _SYS_SCHED_H_ +#include <sys/queue.h> + /* * Posix defines a <sched.h> which may want to include <sys/sched.h> */ @@ -105,6 +107,11 @@ struct schedstate_percpu { int spc_rrticks; /* ticks until roundrobin() */ int spc_pscnt; /* prof/stat counter */ int spc_psdiv; /* prof/stat divisor */ + struct proc *spc_idleproc; /* idle proc for this cpu */ +#ifdef notyet + struct proc *spc_reaper; /* dead proc reaper */ +#endif + LIST_HEAD(,proc) spc_deadproc; }; #ifdef _KERNEL @@ -114,6 +121,8 @@ struct schedstate_percpu { #define SPCF_SHOULDYIELD 0x0002 /* process should yield the CPU */ #define SPCF_SWITCHCLEAR (SPCF_SEENRR|SPCF_SHOULDYIELD) + +#define NQS 32 /* 32 run queues. */ #define PPQ (128 / NQS) /* priorities per queue */ #define NICE_WEIGHT 2 /* priorities per nice level */ #define ESTCPULIM(e) min((e), NICE_WEIGHT * PRIO_MAX - PPQ) @@ -126,7 +135,21 @@ void schedclock(struct proc *); struct cpu_info; void roundrobin(struct cpu_info *); -#define sched_is_idle() (whichqs == 0) +void sched_init_cpu(struct cpu_info *); +void sched_exit(struct proc *); +void mi_switch(void); +void cpu_switchto(struct proc *, struct proc *); +struct proc *sched_chooseproc(void); +void cpu_idle_enter(void); +void cpu_idle_cycle(void); +void cpu_idle_leave(void); + +extern volatile int sched_whichqs; +#define sched_is_idle() (sched_whichqs == 0) + +void sched_init_runqueues(void); +void setrunqueue(struct proc *); +void remrunqueue(struct proc *); /* Inherit the parent's scheduler history */ #define scheduler_fork_hook(parent, child) do { \ diff --git a/sys/uvm/uvm_meter.c b/sys/uvm/uvm_meter.c index 85265e684de..007921d85a2 100644 --- a/sys/uvm/uvm_meter.c +++ b/sys/uvm/uvm_meter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_meter.c,v 1.22 2007/02/14 00:53:48 jsg Exp $ */ +/* $OpenBSD: uvm_meter.c,v 1.23 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: uvm_meter.c,v 1.21 2001/07/14 06:36:03 matt Exp $ */ /* @@ -109,8 +109,10 @@ uvm_loadav(avg) continue; /* FALLTHROUGH */ case SRUN: - case SIDL: case SONPROC: + if (p == p->p_cpu->ci_schedstate.spc_idleproc) + continue; + case SIDL: nrun++; } } |