diff options
Diffstat (limited to 'sys/arch/sparc64')
-rw-r--r-- | sys/arch/sparc64/conf/files.sparc64 | 3 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/locore.s | 382 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/vm_machdep.c | 10 |
3 files changed, 38 insertions, 357 deletions
diff --git a/sys/arch/sparc64/conf/files.sparc64 b/sys/arch/sparc64/conf/files.sparc64 index f3463fa8aa8..c9150465f13 100644 --- a/sys/arch/sparc64/conf/files.sparc64 +++ b/sys/arch/sparc64/conf/files.sparc64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc64,v 1.89 2007/09/10 21:33:16 kettenis Exp $ +# $OpenBSD: files.sparc64,v 1.90 2007/10/10 15:53:53 art Exp $ # $NetBSD: files.sparc64,v 1.50 2001/08/10 20:53:50 eeh Exp $ # maxpartitions must be first item in files.${ARCH} @@ -243,7 +243,6 @@ file arch/sparc64/sparc64/ipifuncs.c multiprocessor file arch/sparc64/sparc64/kgdb_machdep.c kgdb # sparc64/sparc64/locore.s is handled specially in the makefile, # because it must come first in the "ld" command line. -file arch/sparc64/sparc64/locore2.c file arch/sparc64/sparc64/machdep.c file arch/sparc64/sparc64/mem.c file arch/sparc64/sparc64/mutex.S diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index 07767d70bc5..2456810258e 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.83 2007/09/30 21:34:20 kettenis Exp $ */ +/* $OpenBSD: locore.s,v 1.84 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */ /* @@ -5573,350 +5573,39 @@ Lcopyfault: retl mov EFAULT, %o0 - - .data - _ALIGN -/* - * Switch statistics (for later tweaking): - * nswitchdiff = p1 => p2 (i.e., chose different process) - * nswitchexit = number of calls to switchexit() - * _cnt.v_swtch = total calls to swtch+swtchexit - */ - .comm _C_LABEL(nswitchdiff), 4 - .comm _C_LABEL(nswitchexit), 4 - .text -/* - * REGISTER USAGE IN cpu_switch AND switchexit: - * This is split into two phases, more or less - * `before we locate a new proc' and `after'. - * Some values are the same in both phases. - * Note that the %o0-registers are not preserved across - * the psr change when entering a new process, since this - * usually changes the CWP field (hence heavy usage of %g's). - * - * %l1 = <free>; newpcb - * %l2 = %hi(_whichqs); newpsr - * %l3 = p - * %l4 = lastproc - * %l5 = oldpsr (excluding ipl bits) - * %l6 = %hi(cpcb) - * %l7 = %hi(curproc) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4; whichqs; vm - * %o4 = tmp 4; which; sswap - * %o5 = tmp 5; q; <free> - */ - -/* - * switchexit is called only from cpu_exit() before the current process - * has freed its vmspace and kernel stack; we must schedule them to be - * freed. (curproc is already NULL.) - * - * We lay the process to rest by changing to the `idle' kernel stack, - * and note that the `last loaded process' is nonexistent. - */ -ENTRY(switchexit) - /* - * Since we're exiting we don't need to save locals or ins, so - * we won't need the next instruction. - */ -! save %sp, -CC64FSZ, %sp - flushw ! We don't have anything else to run, so why not -#ifdef DEBUG - save %sp, -CC64FSZ, %sp - flushw - restore -#endif /* DEBUG */ - wrpr %g0, PSTATE_KERN, %pstate ! Make sure we're on the right globals - mov %o0, %l2 ! save proc arg for exit2() call XXXXX - - /* - * Change pcb to idle u. area, i.e., set %sp to top of stack - * and %psr to PSR_S|PSR_ET, and set cpcb to point to _idle_u. - * Once we have left the old stack, we can call kmem_free to - * destroy it. Call it any sooner and the register windows - * go bye-bye. - */ - set _C_LABEL(idle_u), %l1 - sethi %hi(CPCB), %l6 -#if 0 - /* Get rid of the stack */ - rdpr %ver, %o0 - wrpr %g0, 0, %canrestore ! Fixup window state regs - and %o0, 0x0f, %o0 - wrpr %g0, 0, %otherwin - wrpr %g0, %o0, %cleanwin ! kernel don't care, but user does - dec 1, %o0 ! What happens if we don't subtract 2? - wrpr %g0, %o0, %cansave - flushw ! DEBUG -#endif /* 0 */ - - stx %l1, [%l6 + %lo(CPCB)] ! cpcb = &idle_u - set _C_LABEL(idle_u) + USPACE - CC64FSZ, %o0 ! set new %sp - sub %o0, BIAS, %sp ! Maybe this should be a save? - wrpr %g0, 0, %canrestore - wrpr %g0, 0, %otherwin - rdpr %ver, %l7 - and %l7, CWP, %l7 - wrpr %l7, 0, %cleanwin - dec 1, %l7 ! NWINDOWS-1-1 - wrpr %l7, %cansave - clr %fp ! End of stack. -#ifdef DEBUG - flushw ! DEBUG - set _C_LABEL(idle_u), %l6 - SET_SP_REDZONE %l6, %l5 -#endif /* DEBUG */ - wrpr %g0, PSTATE_INTR, %pstate ! and then enable traps - call _C_LABEL(exit2) ! exit2(p) - mov %l2, %o0 - -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_lock_idle) ! Acquire sched_lock -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - wrpr %g0, PIL_SCHED, %pil ! Set splsched() - - /* - * Now fall through to `the last switch'. %g6 was set to - * %hi(cpcb), but may have been clobbered in kmem_free, - * so all the registers described below will be set here. - * - * Since the process has exited we can blow its context - * out of the MMUs now to free up those TLB entries rather - * than have more useful ones replaced. - * - * REGISTER USAGE AT THIS POINT: - * %l2 = %hi(_whichqs) - * %l4 = lastproc - * %l5 = oldpsr (excluding ipl bits) - * %l6 = %hi(cpcb) - * %l7 = %hi(curproc) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o3 = whichqs - */ - - INCR _C_LABEL(nswitchexit) ! nswitchexit++; - INCR _C_LABEL(uvmexp)+V_SWTCH ! cnt.v_switch++; - - mov CTX_SECONDARY, %o0 - sethi %hi(_C_LABEL(whichqs)), %l2 - sethi %hi(CPCB), %l6 - sethi %hi(CURPROC), %l7 - ldxa [%o0] ASI_DMMU, %l1 ! Don't demap the kernel - ldx [%l6 + %lo(CPCB)], %l5 - clr %l4 ! lastproc = NULL; - brz,pn %l1, 1f - set DEMAP_CTX_SECONDARY, %l1 ! Demap secondary context - stxa %g1, [%l1] ASI_DMMU_DEMAP - stxa %g1, [%l1] ASI_IMMU_DEMAP - membar #Sync -1: - stxa %g0, [%o0] ASI_DMMU ! Clear out our context - membar #Sync - /* FALLTHROUGH */ - -/* - * When no processes are on the runq, switch - * idles here waiting for something to come ready. - * The registers are set up as noted above. - */ - .globl idle -idle: -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_unlock_idle) ! Release sched_lock -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - stx %g0, [%l7 + %lo(CURPROC)] ! curproc = NULL; -1: ! spin reading _whichqs until nonzero - wrpr %g0, PSTATE_INTR, %pstate ! Make sure interrupts are enabled - wrpr %g0, 0, %pil ! (void) spl0(); - ld [%l2 + %lo(_C_LABEL(whichqs))], %o3 - brnz,pt %o3, notidle ! Something to run - nop -#ifdef UVM_PAGE_IDLE_ZERO - ! Check uvm.page_idle_zero - sethi %hi(_C_LABEL(uvm) + UVM_PAGE_IDLE_ZERO), %o3 - ld [%o3 + %lo(_C_LABEL(uvm) + UVM_PAGE_IDLE_ZERO)], %o3 - brz,pn %o3, 1b - nop - - ! zero some pages - call _C_LABEL(uvm_pageidlezero) - nop -#endif /* UVM_PAGE_IDLE_ZERO */ - ba,a,pt %xcc, 1b - nop ! spitfire bug -notidle: - wrpr %g0, PIL_SCHED, %pil ! (void) splhigh(); -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - call _C_LABEL(sched_lock_idle) ! Grab sched_lock - add %o7, (Lsw_scan-.-4), %o7 ! Return to Lsw_scan directly -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - ba,a,pt %xcc, Lsw_scan - nop ! spitfire bug - -Lsw_panic_rq: - sethi %hi(1f), %o0 - call _C_LABEL(panic) - or %lo(1f), %o0, %o0 Lsw_panic_wchan: - sethi %hi(2f), %o0 - call _C_LABEL(panic) - or %lo(2f), %o0, %o0 + sethi %hi(1f), %o0 + call _C_LABEL(panic) + or %lo(1f), %o0, %o0 Lsw_panic_srun: - sethi %hi(3f), %o0 - call _C_LABEL(panic) - or %lo(3f), %o0, %o0 - .data -1: .asciz "switch rq" -2: .asciz "switch wchan" -3: .asciz "switch SRUN" -idlemsg: .asciz "idle %x %x %x %x" -idlemsg1: .asciz " %x %x %x\r\n" - _ALIGN + sethi %hi(2f), %o0 + call _C_LABEL(panic) + or %lo(2f), %o0, %o0 + .data +1: .asciz "switch wchan" +2: .asciz "switch SRUN" + .text /* - * cpu_switch() picks a process to run and runs it, saving the current - * one away. On the assumption that (since most workstations are - * single user machines) the chances are quite good that the new - * process will turn out to be the current process, we defer saving - * it here until we have found someone to load. If that someone - * is the current process we avoid both store and load. + * cpu_switchto(struct proc *old, struct proc *new) * - * cpu_switch() is always entered at splstatclock or splhigh. - * - * IT MIGHT BE WORTH SAVING BEFORE ENTERING idle TO AVOID HAVING TO - * SAVE LATER WHEN SOMEONE ELSE IS READY ... MUST MEASURE! - * - * Apparently cpu_switch() is called with curproc as the first argument, - * but no port seems to make use of that parameter. + * Save the context of "old" and switch to "new". */ - .globl _C_LABEL(time) -ENTRY(cpu_switch) +ENTRY(cpu_switchto) save %sp, -CC64FSZ, %sp - /* - * REGISTER USAGE AT THIS POINT: - * %l1 = tmp 0 - * %l2 = %hi(_C_LABEL(whichqs)) - * %l3 = p - * %l4 = lastproc - * %l5 = cpcb - * %l6 = %hi(CPCB) - * %l7 = %hi(CURPROC) - * %o0 = tmp 1 - * %o1 = tmp 2 - * %o2 = tmp 3 - * %o3 = tmp 4, then at Lsw_scan, whichqs - * %o4 = tmp 5, then at Lsw_scan, which - * %o5 = tmp 6, then at Lsw_scan, q - */ -#ifdef DEBUG - set swdebug, %o1 - ld [%o1], %o1 - brz,pt %o1, 2f - set 1f, %o0 - call printf - nop - .data -1: .asciz "s" - _ALIGN - .globl swdebug -swdebug: .word 0 - .text -2: -#endif /* DEBUG */ flushw ! We don't have anything else to run, so why not flush -#ifdef DEBUG - save %sp, -CC64FSZ, %sp - flushw - restore -#endif /* DEBUG */ rdpr %pstate, %o1 ! oldpstate = %pstate; wrpr %g0, PSTATE_INTR, %pstate ! make sure we're on normal globals + + mov %i0, %l4 ! oldproc + mov %i1, %l3 ! newproc + sethi %hi(CPCB), %l6 - sethi %hi(_C_LABEL(whichqs)), %l2 ! set up addr regs ldx [%l6 + %lo(CPCB)], %l5 - sethi %hi(CURPROC), %l7 + sethi %hi(CURPROC), %l7 stx %o7, [%l5 + PCB_PC] ! cpcb->pcb_pc = pc; - ldx [%l7 + %lo(CURPROC)], %l4 ! lastproc = curproc; sth %o1, [%l5 + PCB_PSTATE] ! cpcb->pcb_pstate = oldpstate; - stx %g0, [%l7 + %lo(CURPROC)] ! curproc = NULL; - -Lsw_scan: - ld [%l2 + %lo(_C_LABEL(whichqs))], %o3 - -#ifndef POPC - .globl _C_LABEL(__ffstab) - /* - * Optimized inline expansion of `which = ffs(whichqs) - 1'; - * branches to idle if ffs(whichqs) was 0. - */ - set _C_LABEL(__ffstab), %o2 - andcc %o3, 0xff, %o1 ! byte 0 zero? - bz,a,pn %icc, 1f ! yes, try byte 1 - srl %o3, 8, %o0 - ba,pt %icc, 2f ! ffs = ffstab[byte0]; which = ffs - 1; - ldsb [%o2 + %o1], %o0 -1: andcc %o0, 0xff, %o1 ! byte 1 zero? - bz,a,pn %icc, 1f ! yes, try byte 2 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte1] + 7; - ba,pt %icc, 3f - add %o0, 7, %o4 -1: andcc %o0, 0xff, %o1 ! byte 2 zero? - bz,a,pn %icc, 1f ! yes, try byte 3 - srl %o0, 8, %o0 - ldsb [%o2 + %o1], %o0 ! which = ffstab[byte2] + 15; - ba,pt %icc, 3f - add %o0, 15, %o4 -1: ldsb [%o2 + %o0], %o0 ! ffs = ffstab[byte3] + 24 - addcc %o0, 24, %o0 ! (note that ffstab[0] == -24) - bz,pn %icc, idle ! if answer was 0, go idle -! XXX check no delay slot -2: sub %o0, 1, %o4 -3: /* end optimized inline expansion */ - -#else /* POPC */ - /* - * Optimized inline expansion of `which = ffs(whichqs) - 1'; - * branches to idle if ffs(whichqs) was 0. - * - * This version uses popc. - * - * XXXX spitfires and blackbirds don't implement popc. - * - */ - brz,pn %o3, idle ! Don't bother if queues are empty - neg %o3, %o1 ! %o1 = -zz - xnor %o3, %o1, %o2 ! %o2 = zz ^ ~ -zz - popc %o2, %o4 ! which = popc(whichqs) - dec %o4 ! which = ffs(whichqs) - 1 - -#endif /* POPC */ - /* - * We found a nonempty run queue. Take its first process. - */ - set _C_LABEL(qs), %o5 ! q = &qs[which]; - sll %o4, 3+1, %o0 - add %o0, %o5, %o5 - ldx [%o5], %l3 ! p = q->ph_link; - cmp %l3, %o5 ! if (p == q) - be,pn %icc, Lsw_panic_rq ! panic("switch rq"); -! XXX check no delay slot - ldx [%l3], %o0 ! tmp0 = p->p_forw; - stx %o0, [%o5] ! q->ph_link = tmp0; - stx %o5, [%o0 + 8] ! tmp0->p_back = q; - cmp %o0, %o5 ! if (tmp0 == q) - bne 1f -! XXX check no delay slot - mov 1, %o1 ! whichqs &= ~(1 << which); - sll %o1, %o4, %o1 - andn %o3, %o1, %o3 - st %o3, [%l2 + %lo(_C_LABEL(whichqs))] -1: /* * PHASE TWO: NEW REGISTER USAGE: * %l1 = newpcb @@ -5945,7 +5634,6 @@ Lsw_scan: /* * Committed to running process p. - * It may be the same as the one we were running before. */ #if defined(MULTIPROCESSOR) /* @@ -5958,19 +5646,7 @@ Lsw_scan: sethi %hi(CPUINFO_VA+CI_WANT_RESCHED), %o0 st %g0, [%o0 + %lo(CPUINFO_VA+CI_WANT_RESCHED)] ! want_resched = 0; ldx [%l3 + P_ADDR], %l1 ! newpcb = p->p_addr; - stx %g0, [%l3 + 8] ! p->p_back = NULL; -#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - /* - * Done mucking with the run queues, release the - * scheduler lock, but keep interrupts out. - */ - call _C_LABEL(sched_unlock_idle) -#endif /* defined(MULTIPROCESSOR) || defined(LOCKDEBUG) */ - stx %l4, [%l7 + %lo(CURPROC)] ! restore old proc so we can save it - - cmp %l3, %l4 ! p == lastproc? - be,pt %xcc, Lsw_sameproc ! yes, go return 0 - nop + stx %l4, [%l7 + %lo(CURPROC)] ! restore old proc so we can save it /* * Not the old process. Save the old process, if any; @@ -5980,7 +5656,6 @@ Lsw_scan: brz,pn %l4, Lsw_load ! if no old process, go load wrpr %g0, PSTATE_KERN, %pstate - INCR _C_LABEL(nswitchdiff) ! clobbers %o0,%o1,%o2 wb1: flushw ! save all register windows except this one stx %i7, [%l5 + PCB_PC] ! Save rpc @@ -6060,11 +5735,6 @@ Lsw_havectx: membar #Sync ! Maybe we should use flush here? flush %sp -Lsw_sameproc: - /* - * We are resuming the process that was running at the - * call to switch(). Just set psr ipl and return. - */ ! wrpr %g0, 0, %cleanwin ! DEBUG clr %g4 ! This needs to point to the base of the data segment wr %g0, ASI_PRIMARY_NOFAULT, %asi ! Restore default ASI @@ -6072,6 +5742,18 @@ Lsw_sameproc: ret restore +ENTRY(cpu_idle_enter) + retl + nop + +ENTRY(cpu_idle_cycle) + retl + nop + +ENTRY(cpu_idle_leave) + retl + nop + /* * Snapshot the current process so that stack frames are up to date. * Only used just before a crash dump. diff --git a/sys/arch/sparc64/sparc64/vm_machdep.c b/sys/arch/sparc64/sparc64/vm_machdep.c index 5d46c9eb715..88ba247878a 100644 --- a/sys/arch/sparc64/sparc64/vm_machdep.c +++ b/sys/arch/sparc64/sparc64/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.15 2007/06/20 17:29:36 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.16 2007/10/10 15:53:53 art Exp $ */ /* $NetBSD: vm_machdep.c,v 1.38 2001/06/30 00:02:20 eeh Exp $ */ /* @@ -316,8 +316,7 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) * run. */ void -cpu_exit(p) - struct proc *p; +cpu_exit(struct proc *p) { register struct fpstate64 *fs; @@ -328,8 +327,9 @@ cpu_exit(p) } free((void *)fs, M_SUBPROC); } - switchexit(p); - /* NOTREACHED */ + + pmap_deactivate(p); + sched_exit(p); } /* |