Hi,

We're working on a rather large change to how we do context switching
in the kernel and the diff is getting almost ready to get into the
tree. I'd like to have some wider testing on this since it's a quite
a bit of brain surgery on all architectures.

Right now only arm is missing from the diff, so if you have arm machines
you can't test, everyone else should be able to run this. This is
of course -current we're talking about.

What needs to be tested is primarily that everything works and nothing
crashes, but also I'd like people to watch for weird scheduler behavior.
Music not playing, X being slow, top showing weird numbers, stuff like
that.

Please mail me positive test results privately and cc the list if
something loks wrong.

//art

Index: arch/alpha/alpha/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/alpha/alpha/genassym.cf,v
retrieving revision 1.10
diff -u -r1.10 genassym.cf
--- arch/alpha/alpha/genassym.cf	28 May 2007 23:10:10 -0000	1.10
+++ arch/alpha/alpha/genassym.cf	25 Sep 2007 09:53:36 -0000
@@ -103,17 +103,12 @@
 
 # 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
 
Index: arch/alpha/alpha/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/alpha/alpha/locore.s,v
retrieving revision 1.30
diff -u -r1.30 locore.s
--- arch/alpha/alpha/locore.s	28 May 2007 23:10:10 -0000	1.30
+++ arch/alpha/alpha/locore.s	25 Sep 2007 09:53:37 -0000
@@ -716,123 +716,38 @@
 
 /**************************************************************************/
 
-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 @@
 	 * 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 @@
 	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 @@
 
 	ldiq	v0, 1				/* possible ret to savectx() */
 	RET
-	END(cpu_switch)
+	END(cpu_switchto)
 
 #ifndef SMALL_KERNEL
 	/*
@@ -926,6 +841,18 @@
 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()
  *
@@ -944,46 +871,6 @@
 	mov	s2, a0
 	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)
 
 /**************************************************************************/
 
Index: arch/alpha/alpha/machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/alpha/alpha/machdep.c,v
retrieving revision 1.112
diff -u -r1.112 machdep.c
--- arch/alpha/alpha/machdep.c	15 Sep 2007 10:10:37 -0000	1.112
+++ arch/alpha/alpha/machdep.c	25 Sep 2007 09:53:37 -0000
@@ -1874,66 +1874,6 @@
 }
 
 /*
- * 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
Index: arch/alpha/alpha/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/alpha/alpha/vm_machdep.c,v
retrieving revision 1.34
diff -u -r1.34 vm_machdep.c
--- arch/alpha/alpha/vm_machdep.c	3 Sep 2007 01:24:22 -0000	1.34
+++ arch/alpha/alpha/vm_machdep.c	25 Sep 2007 09:53:38 -0000
@@ -114,9 +114,7 @@
 	 * vmspace's context until the switch to proc0 in switch_exit().
 	 */
 	pmap_deactivate(p);
-
-	(void) splhigh();
-	switch_exit(p);
+	sched_exit(p);
 	/* NOTREACHED */
 }
 
Index: arch/amd64/amd64/cpu.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/cpu.c,v
retrieving revision 1.14
diff -u -r1.14 cpu.c
--- arch/amd64/amd64/cpu.c	17 Sep 2007 15:34:38 -0000	1.14
+++ arch/amd64/amd64/cpu.c	25 Sep 2007 09:53:38 -0000
@@ -345,6 +345,7 @@
 #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 @@
 
 	microuptime(&ci->ci_schedstate.spc_runtime);
 	splx(s);
+
+	SCHED_LOCK(s);
+	cpu_switchto(NULL, sched_chooseproc());
 }
 
 #if defined(DDB)
Index: arch/amd64/amd64/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/genassym.cf,v
retrieving revision 1.14
diff -u -r1.14 genassym.cf
--- arch/amd64/amd64/genassym.cf	1 Jun 2007 21:01:51 -0000	1.14
+++ arch/amd64/amd64/genassym.cf	25 Sep 2007 09:53:38 -0000
@@ -33,8 +33,6 @@
 
 struct	proc
 member	p_addr
-member	p_back
-member	p_forw
 member	p_priority
 member	p_stat
 member	p_wchan
Index: arch/amd64/amd64/locore.S
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/locore.S,v
retrieving revision 1.23
diff -u -r1.23 locore.S
--- arch/amd64/amd64/locore.S	12 Sep 2007 18:18:27 -0000	1.23
+++ arch/amd64/amd64/locore.S	25 Sep 2007 09:53:39 -0000
@@ -723,13 +723,8 @@
  * 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 @@
 #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 @@
 	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 @@
 	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_exited:
 	/*
-	 * Third phase: restore saved context.
+	 * Restore saved context.
 	 *
 	 * Registers:
 	 *   %rax, %rcx, %rdx - scratch
@@ -1020,15 +854,13 @@
 	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 @@
 	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);
Index: arch/amd64/amd64/mptramp.S
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/mptramp.S,v
retrieving revision 1.3
diff -u -r1.3 mptramp.S
--- arch/amd64/amd64/mptramp.S	26 Jul 2005 08:38:29 -0000	1.3
+++ arch/amd64/amd64/mptramp.S	25 Sep 2007 09:53:39 -0000
@@ -235,5 +235,4 @@
 	movl    PCB_CR0(%rsi),%eax
 	movq    %rax,%cr0
 	call	_C_LABEL(cpu_hatch)
-	xorq	%r13,%r13
-	jmp	_C_LABEL(mpidle)
+	/* NOTREACHED */
Index: arch/amd64/amd64/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/vm_machdep.c,v
retrieving revision 1.10
diff -u -r1.10 vm_machdep.c
--- arch/amd64/amd64/vm_machdep.c	27 May 2007 20:59:25 -0000	1.10
+++ arch/amd64/amd64/vm_machdep.c	25 Sep 2007 09:53:39 -0000
@@ -169,12 +169,8 @@
 	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);
 }
 
 /*
Index: arch/amd64/conf/files.amd64
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/files.amd64,v
retrieving revision 1.34
diff -u -r1.34 files.amd64
--- arch/amd64/conf/files.amd64	12 Sep 2007 18:18:27 -0000	1.34
+++ arch/amd64/conf/files.amd64	25 Sep 2007 09:53:39 -0000
@@ -18,7 +18,6 @@
 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
Index: arch/aviion/aviion/locore.S
===================================================================
RCS file: /cvs/src/sys/arch/aviion/aviion/locore.S,v
retrieving revision 1.3
diff -u -r1.3 locore.S
--- arch/aviion/aviion/locore.S	20 May 2006 22:40:43 -0000	1.3
+++ arch/aviion/aviion/locore.S	25 Sep 2007 09:53:39 -0000
@@ -343,14 +343,6 @@
 	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 */
 
 /* 
Index: arch/aviion/aviion/machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/aviion/aviion/machdep.c,v
retrieving revision 1.10
diff -u -r1.10 machdep.c
--- arch/aviion/aviion/machdep.c	6 Jun 2007 17:15:11 -0000	1.10
+++ arch/aviion/aviion/machdep.c	25 Sep 2007 09:53:40 -0000
@@ -225,8 +225,6 @@
 {
 	caddr_t v;
 	int sz, i;
-	vsize_t size;
-	int base, residual;
 	vaddr_t minaddr, maxaddr;
 
 	/*
@@ -605,19 +603,18 @@
 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 */
Index: arch/hp300/hp300/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/hp300/hp300/locore.s,v
retrieving revision 1.60
diff -u -r1.60 locore.s
--- arch/hp300/hp300/locore.s	15 May 2007 13:46:22 -0000	1.60
+++ arch/hp300/hp300/locore.s	25 Sep 2007 09:53:41 -0000
@@ -1345,51 +1345,18 @@
  */
 #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 @@
  * 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 @@
 	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)
 
Index: arch/hp300/hp300/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/hp300/hp300/vm_machdep.c,v
retrieving revision 1.43
diff -u -r1.43 vm_machdep.c
--- arch/hp300/hp300/vm_machdep.c	27 May 2007 20:59:25 -0000	1.43
+++ arch/hp300/hp300/vm_machdep.c	25 Sep 2007 09:53:41 -0000
@@ -133,10 +133,10 @@
 cpu_exit(p)
 	struct proc *p;
 {
+	(void)splhigh();
 
-	(void) splhigh();
-	switch_exit(p);
-	/* NOTREACHED */
+	pmap_deactivate(p);
+	sched_exit(p);
 }
 
 /*
Index: arch/hppa/hppa/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/hppa/hppa/genassym.cf,v
retrieving revision 1.30
diff -u -r1.30 genassym.cf
--- arch/hppa/hppa/genassym.cf	14 May 2007 19:54:21 -0000	1.30
+++ arch/hppa/hppa/genassym.cf	25 Sep 2007 09:53:41 -0000
@@ -130,8 +130,6 @@
 
 # proc fields and values
 struct	proc
-member	p_forw
-member	p_back
 member	p_addr
 member	p_priority
 member	p_stat
Index: arch/hppa/hppa/locore.S
===================================================================
RCS file: /cvs/src/sys/arch/hppa/hppa/locore.S,v
retrieving revision 1.155
diff -u -r1.155 locore.S
--- arch/hppa/hppa/locore.S	20 Jul 2007 22:09:23 -0000	1.155
+++ arch/hppa/hppa/locore.S	25 Sep 2007 09:53:42 -0000
@@ -2771,171 +2771,23 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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)
Index: arch/hppa/hppa/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/hppa/hppa/vm_machdep.c,v
retrieving revision 1.61
diff -u -r1.61 vm_machdep.c
--- arch/hppa/hppa/vm_machdep.c	20 Jun 2007 17:29:34 -0000	1.61
+++ arch/hppa/hppa/vm_machdep.c	25 Sep 2007 09:53:43 -0000
@@ -160,12 +160,11 @@
 		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 @@
 		fpu_curpcb = 0;
 	}
 
-	exit2(p);
-	cpu_switch(p);
+	pmap_deactivate(p);
+	sched_exit(p);
 }
 
 void
Index: arch/hppa/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/hppa/include/cpu.h,v
retrieving revision 1.51
diff -u -r1.51 cpu.h
--- arch/hppa/include/cpu.h	20 Jul 2007 22:12:39 -0000	1.51
+++ arch/hppa/include/cpu.h	25 Sep 2007 09:53:43 -0000
@@ -64,6 +64,7 @@
 
 #ifndef _LOCORE
 #ifdef _KERNEL
+#include <sys/queue.h>
 #include <sys/sched.h>
 
 struct cpu_info {
Index: arch/i386/i386/cpu.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/cpu.c,v
retrieving revision 1.25
diff -u -r1.25 cpu.c
--- arch/i386/i386/cpu.c	29 May 2007 18:18:20 -0000	1.25
+++ arch/i386/i386/cpu.c	25 Sep 2007 09:53:43 -0000
@@ -274,6 +274,7 @@
 		identifycpu(ci);
 		cpu_init(ci);
 
+		sched_init_cpu(ci);
 #if NLAPIC > 0
 		/*
 		 * Enable local apic
@@ -295,6 +296,7 @@
 		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 +465,9 @@
 		    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
Index: arch/i386/i386/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/genassym.cf,v
retrieving revision 1.26
diff -u -r1.26 genassym.cf
--- arch/i386/i386/genassym.cf	3 Apr 2007 10:14:47 -0000	1.26
+++ arch/i386/i386/genassym.cf	25 Sep 2007 09:53:43 -0000
@@ -88,8 +88,6 @@
 # proc fields and values
 struct	proc
 member	p_addr
-member	p_back
-member	p_forw
 member	p_priority
 member	p_stat
 member	p_wchan
Index: arch/i386/i386/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/locore.s,v
retrieving revision 1.114
diff -u -r1.114 locore.s
--- arch/i386/i386/locore.s	29 May 2007 23:02:02 -0000	1.114
+++ arch/i386/i386/locore.s	25 Sep 2007 09:53:44 -0000
@@ -1295,279 +1295,52 @@
 	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
+	movl	16(%esp), %esi
+	movl	20(%esp), %edi
 
-	/*
-	 * 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
-	 */
+	xorl	%eax, %eax
 
-	/* 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)
-
-	cmpl	%edx,%eax		# q empty?
-	jne	3f
-
-	btrl	%ebx,%ecx		# yes, clear to indicate empty
-	movl	%ecx,_C_LABEL(whichqs)	# update q status
-
-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 @@
 
 	/* 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 @@
 	lldt	%dx
 #endif /* USER_LDT */
 
-switch_restored:
 	/* Restore cr0 (including FPU state). */
 	movl	PCB_CR0(%esi),%ecx
 #ifdef MULTIPROCESSOR
@@ -1661,103 +1434,29 @@
 	/* 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);
Index: arch/i386/i386/mptramp.s
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/mptramp.s,v
retrieving revision 1.8
diff -u -r1.8 mptramp.s
--- arch/i386/i386/mptramp.s	20 Feb 2007 21:15:01 -0000	1.8
+++ arch/i386/i386/mptramp.s	25 Sep 2007 09:53:44 -0000
@@ -249,9 +249,7 @@
 	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):
Index: arch/i386/i386/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/vm_machdep.c,v
retrieving revision 1.52
diff -u -r1.52 vm_machdep.c
--- arch/i386/i386/vm_machdep.c	27 May 2007 20:59:25 -0000	1.52
+++ arch/i386/i386/vm_machdep.c	25 Sep 2007 09:53:44 -0000
@@ -126,7 +126,6 @@
 		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 @@
 #endif
 
 	pmap_deactivate(p);
-	switch_exit(p);
+	sched_exit(p);
 }
 
 void
Index: arch/i386/include/frame.h
===================================================================
RCS file: /cvs/src/sys/arch/i386/include/frame.h,v
retrieving revision 1.8
diff -u -r1.8 frame.h
--- arch/i386/include/frame.h	27 Nov 2006 18:04:28 -0000	1.8
+++ arch/i386/include/frame.h	25 Sep 2007 09:53:44 -0000
@@ -106,7 +106,6 @@
  * Stack frame inside cpu_switch()
  */
 struct switchframe {
-	int	sf_ppl;
 	int	sf_edi;
 	int	sf_esi;
 	int	sf_ebx;
Index: arch/luna88k/luna88k/locore.S
===================================================================
RCS file: /cvs/src/sys/arch/luna88k/luna88k/locore.S,v
retrieving revision 1.13
diff -u -r1.13 locore.S
--- arch/luna88k/luna88k/locore.S	12 Jan 2007 21:41:53 -0000	1.13
+++ arch/luna88k/luna88k/locore.S	25 Sep 2007 09:53:45 -0000
@@ -150,8 +150,8 @@
 	 * 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 @@
 	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 @@
 	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 @@
 
 #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)
  *
@@ -382,10 +357,6 @@
 
 /* The first processor that XMEMs this becomes the master */
 ASLOCAL(master_mpu)
-	word 0
-
-/* XMEM spin lock -- controls access to master_mpu */
-ASLOCAL(cpu_mutex)
 	word 0
 
 #if defined(DDB) || NKSYMS > 0
Index: arch/luna88k/luna88k/machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/luna88k/luna88k/machdep.c,v
retrieving revision 1.44
diff -u -r1.44 machdep.c
--- arch/luna88k/luna88k/machdep.c	6 Jun 2007 17:15:12 -0000	1.44
+++ arch/luna88k/luna88k/machdep.c	25 Sep 2007 09:53:46 -0000
@@ -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 @@
 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 @@
 #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 @@
 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 @@
 	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;
 
Index: arch/m68k/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/m68k/include/cpu.h,v
retrieving revision 1.17
diff -u -r1.17 cpu.h
--- arch/m68k/include/cpu.h	22 May 2007 10:31:08 -0000	1.17
+++ arch/m68k/include/cpu.h	25 Sep 2007 09:53:46 -0000
@@ -66,6 +66,7 @@
 
 #ifdef _KERNEL
 #ifndef _LOCORE
+#include <sys/queue.h>
 #include <sys/sched.h>
 
 struct cpu_info {
@@ -268,6 +269,9 @@
  * This is used during profiling to integrate system time.
  */
 #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 */
 
Index: arch/m68k/m68k/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/m68k/m68k/genassym.cf,v
retrieving revision 1.12
diff -u -r1.12 genassym.cf
--- arch/m68k/m68k/genassym.cf	15 May 2007 13:46:22 -0000	1.12
+++ arch/m68k/m68k/genassym.cf	25 Sep 2007 09:53:46 -0000
@@ -71,15 +71,10 @@
 
 # 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
Index: arch/m68k/m68k/proc_subr.s
===================================================================
RCS file: /cvs/src/sys/arch/m68k/m68k/proc_subr.s,v
retrieving revision 1.2
diff -u -r1.2 proc_subr.s
--- arch/m68k/m68k/proc_subr.s	2 Jun 2003 23:27:48 -0000	1.2
+++ arch/m68k/m68k/proc_subr.s	25 Sep 2007 09:53:46 -0000
@@ -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
Index: arch/m88k/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/m88k/include/cpu.h,v
retrieving revision 1.22
diff -u -r1.22 cpu.h
--- arch/m88k/include/cpu.h	19 May 2007 20:34:32 -0000	1.22
+++ arch/m88k/include/cpu.h	25 Sep 2007 09:53:46 -0000
@@ -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)
@@ -164,6 +165,8 @@
  */
 #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>
Index: arch/m88k/m88k/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/m88k/m88k/genassym.cf,v
retrieving revision 1.8
diff -u -r1.8 genassym.cf
--- arch/m88k/m88k/genassym.cf	12 May 2007 19:59:52 -0000	1.8
+++ arch/m88k/m88k/genassym.cf	25 Sep 2007 09:53:46 -0000
@@ -49,15 +49,11 @@
 
 # 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
Index: arch/m88k/m88k/m88k_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/m88k/m88k/m88k_machdep.c,v
retrieving revision 1.21
diff -u -r1.21 m88k_machdep.c
--- arch/m88k/m88k/m88k_machdep.c	29 May 2007 18:10:42 -0000	1.21
+++ arch/m88k/m88k/m88k_machdep.c	25 Sep 2007 09:53:46 -0000
@@ -202,50 +202,6 @@
 	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
Index: arch/m88k/m88k/process.S
===================================================================
RCS file: /cvs/src/sys/arch/m88k/m88k/process.S,v
retrieving revision 1.16
diff -u -r1.16 process.S
--- arch/m88k/m88k/process.S	12 May 2007 19:59:52 -0000	1.16
+++ arch/m88k/m88k/process.S	25 Sep 2007 09:53:46 -0000
@@ -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)
+	st	r3,  r11, CI_CURPROC			/* curproc = newproc */
 
-#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	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 @@
 	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)
Index: arch/m88k/m88k/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/m88k/m88k/vm_machdep.c,v
retrieving revision 1.15
diff -u -r1.15 vm_machdep.c
--- arch/m88k/m88k/vm_machdep.c	20 Jun 2007 17:29:36 -0000	1.15
+++ arch/m88k/m88k/vm_machdep.c	25 Sep 2007 09:53:47 -0000
@@ -136,20 +136,17 @@
 
 /*
  * 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);
 }
 
 /*
Index: arch/mac68k/mac68k/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/mac68k/mac68k/locore.s,v
retrieving revision 1.58
diff -u -r1.58 locore.s
--- arch/mac68k/mac68k/locore.s	15 May 2007 13:46:22 -0000	1.58
+++ arch/mac68k/mac68k/locore.s	25 Sep 2007 09:53:47 -0000
@@ -954,52 +954,18 @@
  */
 #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 @@
  * 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 @@
 	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)
 
Index: arch/mac68k/mac68k/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/mac68k/mac68k/vm_machdep.c,v
retrieving revision 1.39
diff -u -r1.39 vm_machdep.c
--- arch/mac68k/mac68k/vm_machdep.c	27 May 2007 20:59:25 -0000	1.39
+++ arch/mac68k/mac68k/vm_machdep.c	25 Sep 2007 09:53:47 -0000
@@ -119,19 +119,18 @@
 
 /*
  * 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);
 }
 
 /*
Index: arch/macppc/macppc/cpu.c
===================================================================
RCS file: /cvs/src/sys/arch/macppc/macppc/cpu.c,v
retrieving revision 1.43
diff -u -r1.43 cpu.c
--- arch/macppc/macppc/cpu.c	23 May 2007 23:40:21 -0000	1.43
+++ arch/macppc/macppc/cpu.c	25 Sep 2007 09:53:48 -0000
@@ -676,7 +676,7 @@
 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 @@
 
 	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
Index: arch/macppc/macppc/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/macppc/macppc/genassym.cf,v
retrieving revision 1.14
diff -u -r1.14 genassym.cf
--- arch/macppc/macppc/genassym.cf	22 Mar 2007 19:26:28 -0000	1.14
+++ arch/macppc/macppc/genassym.cf	25 Sep 2007 09:53:48 -0000
@@ -61,7 +61,6 @@
 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_KERNELSR	pm_sr[PPC_KERNEL_SR]
 
 struct	proc
-member	p_forw
-member	p_back
 member	p_addr
 member	p_stat
 member	p_cpu
Index: arch/macppc/macppc/locore.S
===================================================================
RCS file: /cvs/src/sys/arch/macppc/macppc/locore.S,v
retrieving revision 1.32
diff -u -r1.32 locore.S
--- arch/macppc/macppc/locore.S	20 Mar 2007 20:59:54 -0000	1.32
+++ arch/macppc/macppc/locore.S	25 Sep 2007 09:53:48 -0000
@@ -133,150 +133,41 @@
 	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)
-#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)
+	b	_C_LABEL(cpu_hatch)
+	/* NOTREACHED */
 #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)
+	stw	%r4,CI_CURPROC(%r5)	/* record new process */
 
-	mfmsr	%r3
-	ori	%r3,%r3,PSL_EE		/* Now we can interrupt again */
-	mtmsr	%r3
+	li	%r31,SONPROC
+	stb	%r31,P_STAT(%r4)
 
-	cmpl	0,%r31,%r30		/* is it the same process? */
-	beq	switch_return
-
-	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 @@
 	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 @@
 	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 @@
 	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
Index: arch/mips64/mips64/context.S
===================================================================
RCS file: /cvs/src/sys/arch/mips64/mips64/context.S,v
retrieving revision 1.13
diff -u -r1.13 context.S
--- arch/mips64/mips64/context.S	16 Jul 2007 20:22:18 -0000	1.13
+++ arch/mips64/mips64/context.S	25 Sep 2007 09:53:49 -0000
@@ -69,92 +69,11 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 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 @@
 	ITLBNOPFIX
 	j	ra
 	nop
-4:
-	PANIC("cpu_switch")			# nothing in queue
-END(cpu_switch)
+END(cpu_switchto)
Index: arch/mips64/mips64/db_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/mips64/mips64/db_machdep.c,v
retrieving revision 1.12
diff -u -r1.12 db_machdep.c
--- arch/mips64/mips64/db_machdep.c	3 Sep 2007 01:15:50 -0000	1.12
+++ arch/mips64/mips64/db_machdep.c	25 Sep 2007 09:53:49 -0000
@@ -221,7 +221,6 @@
 	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 @@
 	}
 
 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) {
Index: arch/mips64/mips64/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/mips64/mips64/vm_machdep.c,v
retrieving revision 1.15
diff -u -r1.15 vm_machdep.c
--- arch/mips64/mips64/vm_machdep.c	3 Sep 2007 17:35:51 -0000	1.15
+++ arch/mips64/mips64/vm_machdep.c	25 Sep 2007 09:53:49 -0000
@@ -134,9 +134,9 @@
 	if (machFPCurProcPtr == p)
 		machFPCurProcPtr = (struct proc *)0;
 
-	(void) splhigh();
-	switch_exit(p);
-	/* NOTREACHED */
+	(void)splhigh();
+	pmap_deactivate(p);
+	sched_exit(p);
 }
 
 /*
Index: arch/mvme68k/mvme68k/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/mvme68k/mvme68k/locore.s,v
retrieving revision 1.54
diff -u -r1.54 locore.s
--- arch/mvme68k/mvme68k/locore.s	15 May 2007 13:46:22 -0000	1.54
+++ arch/mvme68k/mvme68k/locore.s	25 Sep 2007 09:53:50 -0000
@@ -1165,51 +1165,18 @@
  */
 #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 @@
  * 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 @@
 	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)
 
Index: arch/mvme68k/mvme68k/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/mvme68k/mvme68k/vm_machdep.c,v
retrieving revision 1.45
diff -u -r1.45 vm_machdep.c
--- arch/mvme68k/mvme68k/vm_machdep.c	20 Jun 2007 17:29:36 -0000	1.45
+++ arch/mvme68k/mvme68k/vm_machdep.c	25 Sep 2007 09:53:50 -0000
@@ -117,20 +117,18 @@
 
 /*
  * 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);
 }
 
 /*
Index: arch/mvme88k/mvme88k/locore.S
===================================================================
RCS file: /cvs/src/sys/arch/mvme88k/mvme88k/locore.S,v
retrieving revision 1.49
diff -u -r1.49 locore.S
--- arch/mvme88k/mvme88k/locore.S	8 May 2006 14:03:35 -0000	1.49
+++ arch/mvme88k/mvme88k/locore.S	25 Sep 2007 09:53:50 -0000
@@ -346,14 +346,6 @@
 	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 */
 
 /*
Index: arch/mvme88k/mvme88k/machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/mvme88k/mvme88k/machdep.c,v
retrieving revision 1.192
diff -u -r1.192 machdep.c
--- arch/mvme88k/mvme88k/machdep.c	6 Jun 2007 17:15:12 -0000	1.192
+++ arch/mvme88k/mvme88k/machdep.c	25 Sep 2007 09:53:51 -0000
@@ -719,19 +719,18 @@
 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 */
Index: arch/powerpc/conf/files.powerpc
===================================================================
RCS file: /cvs/src/sys/arch/powerpc/conf/files.powerpc,v
retrieving revision 1.42
diff -u -r1.42 files.powerpc
--- arch/powerpc/conf/files.powerpc	22 Mar 2007 19:26:27 -0000	1.42
+++ arch/powerpc/conf/files.powerpc	25 Sep 2007 09:53:51 -0000
@@ -2,7 +2,6 @@
 #
 
 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
Index: arch/powerpc/include/pcb.h
===================================================================
RCS file: /cvs/src/sys/arch/powerpc/include/pcb.h,v
retrieving revision 1.10
diff -u -r1.10 pcb.h
--- arch/powerpc/include/pcb.h	20 Mar 2007 20:59:53 -0000	1.10
+++ arch/powerpc/include/pcb.h	25 Sep 2007 09:53:51 -0000
@@ -49,7 +49,6 @@
 	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 */
Index: arch/powerpc/powerpc/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/powerpc/powerpc/vm_machdep.c,v
retrieving revision 1.44
diff -u -r1.44 vm_machdep.c
--- arch/powerpc/powerpc/vm_machdep.c	20 Jun 2007 17:29:36 -0000	1.44
+++ arch/powerpc/powerpc/vm_machdep.c	25 Sep 2007 09:53:51 -0000
@@ -123,7 +123,6 @@
 	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 @@
 		pool_put(&ppc_vecpl, pcb->pcb_vr);
 #endif /* ALTIVEC */
 	
-	(void)splsched();
-	switchexit(p);
+	pmap_deactivate(p);
+	sched_exit(p);
 }
 
 /*
Index: arch/sgi/localbus/macebus.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/localbus/macebus.c,v
retrieving revision 1.26
diff -u -r1.26 macebus.c
--- arch/sgi/localbus/macebus.c	9 Jul 2007 21:40:24 -0000	1.26
+++ arch/sgi/localbus/macebus.c	25 Sep 2007 09:53:52 -0000
@@ -780,7 +780,6 @@
 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 @@
 	/* 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);
Index: arch/sgi/sgi/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/genassym.cf,v
retrieving revision 1.9
diff -u -r1.9 genassym.cf
--- arch/sgi/sgi/genassym.cf	18 Jun 2007 20:25:55 -0000	1.9
+++ arch/sgi/sgi/genassym.cf	25 Sep 2007 09:53:52 -0000
@@ -38,9 +38,7 @@
 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
Index: arch/sh/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/sh/include/cpu.h,v
retrieving revision 1.10
diff -u -r1.10 cpu.h
--- arch/sh/include/cpu.h	6 Jun 2007 17:15:12 -0000	1.10
+++ arch/sh/include/cpu.h	25 Sep 2007 09:53:52 -0000
@@ -125,6 +125,11 @@
  * 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 */
 
 /*
Index: arch/sh/sh/genassym.cf
===================================================================
RCS file: /cvs/src/sys/arch/sh/sh/genassym.cf,v
retrieving revision 1.3
diff -u -r1.3 genassym.cf
--- arch/sh/sh/genassym.cf	14 May 2007 07:05:49 -0000	1.3
+++ arch/sh/sh/genassym.cf	25 Sep 2007 09:53:52 -0000
@@ -54,8 +54,6 @@
 
 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
Index: arch/sh/sh/locore_c.c
===================================================================
RCS file: /cvs/src/sys/arch/sh/sh/locore_c.c,v
retrieving revision 1.5
diff -u -r1.5 locore_c.c
--- arch/sh/sh/locore_c.c	9 Sep 2007 11:57:55 -0000	1.5
+++ arch/sh/sh/locore_c.c	25 Sep 2007 09:53:52 -0000
@@ -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 @@
 	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 @@
 	}
 
 	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 @@
 	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
Index: arch/sh/sh/locore_subr.S
===================================================================
RCS file: /cvs/src/sys/arch/sh/sh/locore_subr.S,v
retrieving revision 1.6
diff -u -r1.6 locore_subr.S
--- arch/sh/sh/locore_subr.S	2 Mar 2007 06:11:54 -0000	1.6
+++ arch/sh/sh/locore_subr.S	25 Sep 2007 09:53:53 -0000
@@ -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 @@
 	/* 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,48 +247,8 @@
 	 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
 /*
Index: arch/sh/sh/sh_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sh/sh/sh_machdep.c,v
retrieving revision 1.16
diff -u -r1.16 sh_machdep.c
--- arch/sh/sh/sh_machdep.c	6 Jun 2007 17:15:12 -0000	1.16
+++ arch/sh/sh/sh_machdep.c	25 Sep 2007 09:53:53 -0000
@@ -716,45 +716,6 @@
 	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.
  */
Index: arch/solbourne/solbourne/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/solbourne/solbourne/locore.s,v
retrieving revision 1.8
diff -u -r1.8 locore.s
--- arch/solbourne/solbourne/locore.s	15 Apr 2006 17:36:47 -0000	1.8
+++ arch/solbourne/solbourne/locore.s	25 Sep 2007 09:53:55 -0000
@@ -3233,291 +3233,52 @@
 	.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 @@
 	 */
 
 	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
 
Index: arch/sparc/conf/files.sparc
===================================================================
RCS file: /cvs/src/sys/arch/sparc/conf/files.sparc,v
retrieving revision 1.78
diff -u -r1.78 files.sparc
--- arch/sparc/conf/files.sparc	29 May 2007 09:54:03 -0000	1.78
+++ arch/sparc/conf/files.sparc	25 Sep 2007 09:53:55 -0000
@@ -291,7 +291,6 @@
 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
Index: arch/sparc/sparc/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/sparc/sparc/locore.s,v
retrieving revision 1.72
diff -u -r1.72 locore.s
--- arch/sparc/sparc/locore.s	29 May 2007 09:54:01 -0000	1.72
+++ arch/sparc/sparc/locore.s	25 Sep 2007 09:53:58 -0000
@@ -4383,290 +4383,52 @@
 	.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 @@
 	 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.
Index: arch/sparc/sparc/locore2.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc/sparc/locore2.c,v
retrieving revision 1.5
diff -u -r1.5 locore2.c
--- arch/sparc/sparc/locore2.c	2 Jun 2003 23:27:55 -0000	1.5
+++ arch/sparc/sparc/locore2.c	25 Sep 2007 09:53:58 -0000
@@ -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);
-}
Index: arch/sparc/sparc/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc/sparc/vm_machdep.c,v
retrieving revision 1.49
diff -u -r1.49 vm_machdep.c
--- arch/sparc/sparc/vm_machdep.c	20 Jun 2007 17:29:36 -0000	1.49
+++ arch/sparc/sparc/vm_machdep.c	25 Sep 2007 09:53:58 -0000
@@ -449,10 +449,9 @@
 /*
  * 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 @@
 		free((void *)fs, M_SUBPROC);
 	}
 
-	switchexit(p);
-	/* NOTREACHED */
+	pmap_deactivate(p);
+	sched_exit(p);
 }
 
 /*
Index: arch/sparc64/conf/files.sparc64
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/conf/files.sparc64,v
retrieving revision 1.89
diff -u -r1.89 files.sparc64
--- arch/sparc64/conf/files.sparc64	10 Sep 2007 21:33:16 -0000	1.89
+++ arch/sparc64/conf/files.sparc64	25 Sep 2007 09:53:59 -0000
@@ -243,7 +243,6 @@
 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
Index: arch/sparc64/sparc64/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/sparc64/locore.s,v
retrieving revision 1.82
diff -u -r1.82 locore.s
--- arch/sparc64/sparc64/locore.s	22 Sep 2007 20:04:51 -0000	1.82
+++ arch/sparc64/sparc64/locore.s	25 Sep 2007 09:54:03 -0000
@@ -5578,350 +5578,39 @@
 	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_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!
+ * cpu_switchto(struct proc *old, struct proc *new)
  *
- * 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
@@ -5950,7 +5639,6 @@
 
 	/*
 	 * Committed to running process p.
-	 * It may be the same as the one we were running before.
 	 */
 #if defined(MULTIPROCESSOR)
 	/*
@@ -5963,19 +5651,7 @@
 	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;
@@ -5985,7 +5661,6 @@
 	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
@@ -6065,17 +5740,24 @@
 	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
 	wrpr	%g0, PSTATE_INTR, %pstate
 	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.
Index: arch/sparc64/sparc64/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/sparc64/vm_machdep.c,v
retrieving revision 1.15
diff -u -r1.15 vm_machdep.c
--- arch/sparc64/sparc64/vm_machdep.c	20 Jun 2007 17:29:36 -0000	1.15
+++ arch/sparc64/sparc64/vm_machdep.c	25 Sep 2007 09:54:03 -0000
@@ -316,8 +316,7 @@
  * run.
  */
 void
-cpu_exit(p)
-	struct proc *p;
+cpu_exit(struct proc *p)
 {
 	register struct fpstate64 *fs;
 
@@ -328,8 +327,9 @@
 		}
 		free((void *)fs, M_SUBPROC);
 	}
-	switchexit(p);
-	/* NOTREACHED */
+
+	pmap_deactivate(p);
+	sched_exit(p);
 }
 
 /*
Index: arch/vax/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/vax/include/cpu.h,v
retrieving revision 1.25
diff -u -r1.25 cpu.h
--- arch/vax/include/cpu.h	16 May 2007 05:19:13 -0000	1.25
+++ arch/vax/include/cpu.h	25 Sep 2007 09:54:03 -0000
@@ -129,6 +129,10 @@
  */
 #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.
  */
Index: arch/vax/include/macros.h
===================================================================
RCS file: /cvs/src/sys/arch/vax/include/macros.h,v
retrieving revision 1.14
diff -u -r1.14 macros.h
--- arch/vax/include/macros.h	6 Nov 2006 21:31:36 -0000	1.14
+++ arch/vax/include/macros.h	25 Sep 2007 09:54:03 -0000
@@ -232,15 +232,10 @@
 	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
Index: arch/vax/vax/subr.s
===================================================================
RCS file: /cvs/src/sys/arch/vax/vax/subr.s,v
retrieving revision 1.26
diff -u -r1.26 subr.s
--- arch/vax/vax/subr.s	16 May 2007 05:19:15 -0000	1.26
+++ arch/vax/vax/subr.s	25 Sep 2007 09:54:04 -0000
@@ -240,114 +240,37 @@
 #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. 
Index: arch/vax/vax/vm_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/vax/vax/vm_machdep.c,v
retrieving revision 1.34
diff -u -r1.34 vm_machdep.c
--- arch/vax/vax/vm_machdep.c	20 Jun 2007 17:29:36 -0000	1.34
+++ arch/vax/vax/vm_machdep.c	25 Sep 2007 09:54:04 -0000
@@ -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.
@@ -109,13 +119,6 @@
 	tf = (struct trapframe *)((u_int)p2->p_addr + USPACE) - 1;
 	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;
Index: conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.410
diff -u -r1.410 files
--- conf/files	12 Sep 2007 12:59:55 -0000	1.410
+++ conf/files	25 Sep 2007 09:54:05 -0000
@@ -645,6 +645,7 @@
 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
Index: kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.144
diff -u -r1.144 init_main.c
--- kern/init_main.c	10 Sep 2007 18:49:45 -0000	1.144
+++ kern/init_main.c	25 Sep 2007 09:54:07 -0000
@@ -327,7 +327,9 @@
 	(void)chgproccnt(0, 1);
 
 	/* Initialize run queues */
-	rqinit();
+	sched_init_runqueues();
+	sleep_queue_init();
+	sched_init_cpu(curcpu());
 
 	/* Initialize work queues */
 	workq_init();
Index: kern/kern_clock.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_clock.c,v
retrieving revision 1.64
diff -u -r1.64 kern_clock.c
--- kern/kern_clock.c	16 May 2007 17:27:30 -0000	1.64
+++ kern/kern_clock.c	25 Sep 2007 09:54:07 -0000
@@ -546,7 +546,7 @@
 			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
Index: kern/kern_exit.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.71
diff -u -r1.71 kern_exit.c
--- kern/kern_exit.c	12 Apr 2007 22:14:15 -0000	1.71
+++ kern/kern_exit.c	25 Sep 2007 09:54:08 -0000
@@ -315,16 +315,8 @@
 	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 @@
 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);
 }
 
 /*
@@ -395,6 +383,8 @@
 	struct proc *p;
 
 	KERNEL_PROC_UNLOCK(curproc);
+
+	SCHED_ASSERT_UNLOCKED();
 
 	for (;;) {
 		mtx_enter(&deadproc_mutex);
Index: kern/kern_fork.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.92
diff -u -r1.92 kern_fork.c
--- kern/kern_fork.c	25 Jul 2007 23:11:52 -0000	1.92
+++ kern/kern_fork.c	25 Sep 2007 09:54:08 -0000
@@ -224,7 +224,6 @@
 
 	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 @@
 
 	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
Index: kern/kern_proc.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_proc.c,v
retrieving revision 1.35
diff -u -r1.35 kern_proc.c
--- kern/kern_proc.c	7 Sep 2007 15:00:20 -0000	1.35
+++ kern/kern_proc.c	25 Sep 2007 09:54:08 -0000
@@ -377,8 +377,8 @@
 	    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",
Index: kern/kern_sched.c
===================================================================
RCS file: kern/kern_sched.c
diff -N kern/kern_sched.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kern/kern_sched.c	25 Sep 2007 09:54:08 -0000
@@ -0,0 +1,242 @@
+/*	$OpenBSD$	*/
+/*
+ * 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);	
+}
Index: kern/kern_synch.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_synch.c,v
retrieving revision 1.80
diff -u -r1.80 kern_synch.c
--- kern/kern_synch.c	16 May 2007 17:27:30 -0000	1.80
+++ kern/kern_synch.c	25 Sep 2007 09:54:08 -0000
@@ -67,10 +67,17 @@
  */
 #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 @@
 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 @@
 	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 @@
 		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 @@
 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 @@
 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 @@
 				need_resched(p->p_cpu);
 				/* END INLINE EXPANSION */
 
-				if (n != 0)
-					goto restart;
-				else
-					break;
 			}
-		} else
-			q = &p->p_forw;
+		}
 	}
 	SCHED_UNLOCK(s);
 }
Index: kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.157
diff -u -r1.157 kern_sysctl.c
--- kern/kern_sysctl.c	7 Sep 2007 15:00:20 -0000	1.157
+++ kern/kern_sysctl.c	25 Sep 2007 09:54:10 -0000
@@ -1280,9 +1280,7 @@
 		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;
Index: kern/sched_bsd.c
===================================================================
RCS file: /cvs/src/sys/kern/sched_bsd.c,v
retrieving revision 1.12
diff -u -r1.12 sched_bsd.c
--- kern/sched_bsd.c	18 May 2007 16:10:15 -0000	1.12
+++ kern/sched_bsd.c	25 Sep 2007 09:54:10 -0000
@@ -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 @@
 	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 @@
 	/*
 	 * 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 @@
 	 */
 	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 @@
 	 * 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
@@ -458,20 +462,6 @@
 		__mp_acquire_count(&kernel_lock, hold_count);
 	__mp_acquire_count(&sched_lock, sched_count + 1);
 #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
Index: sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.100
diff -u -r1.100 proc.h
--- sys/proc.h	25 Jul 2007 23:11:53 -0000	1.100
+++ sys/proc.h	25 Sep 2007 09:54:11 -0000
@@ -148,8 +148,7 @@
 #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 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	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	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_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)
Index: sys/sched.h
===================================================================
RCS file: /cvs/src/sys/sys/sched.h,v
retrieving revision 1.16
diff -u -r1.16 sched.h
--- sys/sched.h	18 May 2007 14:41:55 -0000	1.16
+++ sys/sched.h	25 Sep 2007 09:54:11 -0000
@@ -105,6 +105,11 @@
 	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 +119,8 @@
 #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 +133,21 @@
 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 {				\
Index: uvm/uvm_meter.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_meter.c,v
retrieving revision 1.22
diff -u -r1.22 uvm_meter.c
--- uvm/uvm_meter.c	14 Feb 2007 00:53:48 -0000	1.22
+++ uvm/uvm_meter.c	25 Sep 2007 09:54:11 -0000
@@ -109,6 +109,8 @@
 				continue;
 		/* FALLTHROUGH */
 		case SRUN:
+			if (p == p->p_cpu->ci_schedstate.spc_idleproc)
+				continue;
 		case SIDL:
 		case SONPROC:
 			nrun++;

