version 1.148, 2001/09/13 13:25:48 |
version 1.148.4.11, 2002/08/01 02:43:28 |
Line 204 _C_LABEL(kgdb_stack): |
|
Line 204 _C_LABEL(kgdb_stack): |
|
*/ |
*/ |
cpcb = CPUINFO_VA + CPUINFO_CURPCB |
cpcb = CPUINFO_VA + CPUINFO_CURPCB |
|
|
/* curproc points to the current process that has the CPU */ |
/* curlwp points to the current LWP that has the CPU */ |
curproc = CPUINFO_VA + CPUINFO_CURPROC |
curlwp = CPUINFO_VA + CPUINFO_CURLWP |
|
|
/* |
/* |
* cputyp is the current cpu type, used to distinguish between |
* cputyp is the current cpu type, used to distinguish between |
|
|
#endif |
#endif |
#endif |
#endif |
|
|
|
#if !defined(SUN4D) |
|
sun4d_notsup: |
|
.asciz "cr .( NetBSD/sparc: this kernel does not support the sun4d) cr" |
|
#endif |
#if !defined(SUN4M) |
#if !defined(SUN4M) |
sun4m_notsup: |
sun4m_notsup: |
.asciz "cr .( NetBSD/sparc: this kernel does not support the sun4m) cr" |
.asciz "cr .( NetBSD/sparc: this kernel does not support the sun4m) cr" |
|
|
bl,a ctw_merge ! all ok if only 1 |
bl,a ctw_merge ! all ok if only 1 |
std %l0, [%sp] |
std %l0, [%sp] |
add %sp, 7*8, %g5 ! check last addr too |
add %sp, 7*8, %g5 ! check last addr too |
add %g6, 62, %g6 ! restore %g6 to `pgofset' |
add %g6, 62, %g6 /* restore %g6 to `pgofset' */ |
PTE_OF_ADDR(%g5, %g7, ctw_invalid, %g6, NOP_ON_4M_3) |
PTE_OF_ADDR(%g5, %g7, ctw_invalid, %g6, NOP_ON_4M_3) |
CMP_PTE_USER_WRITE(%g7, %g6, NOP_ON_4M_4) |
CMP_PTE_USER_WRITE(%g7, %g6, NOP_ON_4M_4) |
be,a ctw_merge ! all ok: store <l0,l1> and merge |
be,a ctw_merge ! all ok: store <l0,l1> and merge |
Line 2465 softintr_common: |
|
Line 2469 softintr_common: |
|
*/ |
*/ |
#if defined(SUN4M) |
#if defined(SUN4M) |
_ENTRY(_C_LABEL(sparc_interrupt4m)) |
_ENTRY(_C_LABEL(sparc_interrupt4m)) |
|
#if !defined(MSIIEP) /* "normal" sun4m */ |
mov 1, %l4 |
mov 1, %l4 |
sethi %hi(CPUINFO_VA+CPUINFO_INTREG), %l6 |
sethi %hi(CPUINFO_VA+CPUINFO_INTREG), %l6 |
ld [%l6 + %lo(CPUINFO_VA+CPUINFO_INTREG)], %l6 |
ld [%l6 + %lo(CPUINFO_VA+CPUINFO_INTREG)], %l6 |
Line 2478 _ENTRY(_C_LABEL(sparc_interrupt4m)) |
|
Line 2483 _ENTRY(_C_LABEL(sparc_interrupt4m)) |
|
sll %l4, 16, %l5 |
sll %l4, 16, %l5 |
st %l5, [%l6 + ICR_PI_CLR_OFFSET] |
st %l5, [%l6 + ICR_PI_CLR_OFFSET] |
b,a softintr_common |
b,a softintr_common |
#endif |
#else /* MSIIEP */ |
|
sethi %hi(MSIIEP_PCIC_VA), %l6 |
|
mov 1, %l4 |
|
ld [%l6 + PCIC_PROC_IPR_REG], %l5 ! get pending interrupts |
|
sll %l4, %l3, %l4 |
|
btst %l4, %l5 ! has pending hw intr at this level? |
|
bnz sparc_interrupt_common |
|
nop |
|
|
|
! a soft interrupt; clear its bit in softintr clear register |
|
b softintr_common |
|
sth %l4, [%l6 + PCIC_SOFT_INTR_CLEAR_REG] |
|
#endif /* MSIIEP */ |
|
#endif /* SUN4M */ |
|
|
_ENTRY(_C_LABEL(sparc_interrupt44c)) |
_ENTRY(_C_LABEL(sparc_interrupt44c)) |
sparc_interrupt_common: |
sparc_interrupt_common: |
|
|
*/ |
*/ |
sethi %hi(INTRREG_VA), %o0 |
sethi %hi(INTRREG_VA), %o0 |
ldub [%o0 + %lo(INTRREG_VA)], %o1 |
ldub [%o0 + %lo(INTRREG_VA)], %o1 |
andn %o0, IE_ALLIE, %o1 |
andn %o1, IE_ALLIE, %o1 |
stb %o1, [%o0 + %lo(INTRREG_VA)] |
stb %o1, [%o0 + %lo(INTRREG_VA)] |
wr %l0, PSR_ET, %psr ! okay, turn traps on again |
wr %l0, PSR_ET, %psr ! okay, turn traps on again |
|
|
|
|
*/ |
*/ |
sethi %hi(INTRREG_VA), %o0 |
sethi %hi(INTRREG_VA), %o0 |
ldub [%o0 + %lo(INTRREG_VA)], %o1 |
ldub [%o0 + %lo(INTRREG_VA)], %o1 |
andn %o0, IE_ALLIE, %o1 |
andn %o1, IE_ALLIE, %o1 |
stb %o1, [%o0 + %lo(INTRREG_VA)] |
stb %o1, [%o0 + %lo(INTRREG_VA)] |
wr %l0, PSR_ET, %psr ! okay, turn traps on again |
wr %l0, PSR_ET, %psr ! okay, turn traps on again |
|
|
|
|
bnz,a 1f ! |
bnz,a 1f ! |
mov %o0, %o1 ! shift int clear bit to SOFTINT 15 |
mov %o0, %o1 ! shift int clear bit to SOFTINT 15 |
|
|
set _C_LABEL(nmi_hard), %o3 ! it's a hardint; switch handler |
set _C_LABEL(nmi_hard), %o3 /* it's a hardint; switch handler */ |
|
|
/* |
/* |
* Level 15 interrupts are nonmaskable, so with traps off, |
* Level 15 interrupts are nonmaskable, so with traps off, |
|
|
|
|
!cmp %o0, 0 ! was this a soft nmi |
!cmp %o0, 0 ! was this a soft nmi |
!be 4f |
!be 4f |
!XXX - we need to unblock `mask all ints' only on a hard nmi |
/* XXX - we need to unblock `mask all ints' only on a hard nmi */ |
|
|
! enable interrupts again (safe, we disabled traps again above) |
! enable interrupts again (safe, we disabled traps again above) |
sethi %hi(ICR_SI_CLR), %o0 |
sethi %hi(ICR_SI_CLR), %o0 |
|
|
* we have to be sure to use only pc-relative addressing. |
* we have to be sure to use only pc-relative addressing. |
*/ |
*/ |
|
|
#ifdef DDB |
|
/* |
/* |
* We now use the bootinfo method to pass arguments, and the new |
* We now use the bootinfo method to pass arguments, and the new |
* magic number indicates that. A pointer to esym is passed in |
* magic number indicates that. A pointer to the kernel top, i.e. |
* %o4[0] and the bootinfo structure is passed in %o4[1]. |
* the first address after the load kernel image (including DDB |
|
* symbols, if any) is passed in %o4[0] and the bootinfo structure |
|
* is passed in %o4[1]. |
|
* |
|
* A magic number is passed in %o5 to allow for bootloaders |
|
* that know nothing about the bootinfo structure or previous |
|
* DDB symbol loading conventions. |
* |
* |
* For compatibility with older versions, we check for DDB arguments |
* For compatibility with older versions, we check for DDB arguments |
* if the older magic number is there. The loader passes `esym' in |
* if the older magic number is there. The loader passes `kernel_top' |
* %o4. |
* (previously known as `esym') in %o4. |
* A DDB magic number is passed in %o5 to allow for bootloaders |
* |
* that know nothing about DDB symbol loading conventions. |
|
* Note: we don't touch %o1-%o3; SunOS bootloaders seem to use them |
* Note: we don't touch %o1-%o3; SunOS bootloaders seem to use them |
* for their own mirky business. |
* for their own mirky business. |
* |
* |
* Pre-NetBSD 1.3 bootblocks had KERNBASE compiled in, and used |
* Pre-NetBSD 1.3 bootblocks had KERNBASE compiled in, and used it |
* it to compute the value of `esym'. In order to successfully |
* to compute the value of `kernel_top' (previously known as `esym'). |
* boot a kernel built with a different value for KERNBASE using |
* In order to successfully boot a kernel built with a different value |
* old bootblocks, we fixup `esym' here by the difference between |
* for KERNBASE using old bootblocks, we fixup `kernel_top' here by |
* KERNBASE and the old value (known to be 0xf8000000) compiled |
* the difference between KERNBASE and the old value (known to be |
* into pre-1.3 bootblocks. |
* 0xf8000000) compiled into pre-1.3 bootblocks. |
* We use the magic number passed as the sixth argument to |
|
* distinguish bootblock versions. |
|
*/ |
*/ |
set KERNBASE, %l4 |
set KERNBASE, %l4 |
|
|
|
|
nop |
nop |
|
|
/* The loader has passed to us a `bootinfo' structure */ |
/* The loader has passed to us a `bootinfo' structure */ |
ld [%o4], %l3 ! 1st word is esym |
ld [%o4], %l3 ! 1st word is kernel_top |
add %l3, %l4, %o5 ! relocate |
add %l3, %l4, %o5 ! relocate: + KERNBASE |
sethi %hi(_C_LABEL(esym) - KERNBASE), %l3 ! store esym |
sethi %hi(_C_LABEL(kernel_top) - KERNBASE), %l3 ! and store it |
st %o5, [%l3 + %lo(_C_LABEL(esym) - KERNBASE)] |
st %o5, [%l3 + %lo(_C_LABEL(kernel_top) - KERNBASE)] |
|
|
ld [%o4 + 4], %l3 ! 2nd word is bootinfo |
ld [%o4 + 4], %l3 ! 2nd word is bootinfo |
add %l3, %l4, %o5 ! relocate |
add %l3, %l4, %o5 ! relocate |
sethi %hi(_C_LABEL(bootinfo) - KERNBASE), %l3 ! store bootinfo |
sethi %hi(_C_LABEL(bootinfo) - KERNBASE), %l3 ! store bootinfo |
st %o5, [%l3 + %lo(_C_LABEL(bootinfo) - KERNBASE)] |
st %o5, [%l3 + %lo(_C_LABEL(bootinfo) - KERNBASE)] |
b,a 3f |
b,a 4f |
|
|
1: |
1: |
|
#ifdef DDB |
/* Check for old-style DDB loader magic */ |
/* Check for old-style DDB loader magic */ |
set 0x44444231, %l3 ! ddb magic |
set 0x44444231, %l3 ! Is it DDB_MAGIC1? |
cmp %o5, %l3 |
cmp %o5, %l3 |
be,a 2f |
be,a 2f |
clr %l4 ! if DDB_MAGIC1, clear %l4 |
clr %l4 ! if DDB_MAGIC1, clear %l4 |
|
|
set 0x44444230, %l3 ! compat magic |
set 0x44444230, %l3 ! Is it DDB_MAGIC0? |
cmp %o5, %l3 |
cmp %o5, %l3 ! if so, need to relocate %o4 |
bne 3f |
bne 3f /* if not, there's no bootloader info */ |
|
|
! note: %l4 set to KERNBASE above. |
! note: %l4 set to KERNBASE above. |
set 0xf8000000, %l5 ! compute correction term: |
set 0xf8000000, %l5 ! compute correction term: |
|
|
tst %o4 ! do we have the symbols? |
tst %o4 ! do we have the symbols? |
bz 3f |
bz 3f |
sub %o4, %l4, %o4 ! apply compat correction |
sub %o4, %l4, %o4 ! apply compat correction |
sethi %hi(_C_LABEL(esym) - KERNBASE), %l3 ! store esym |
sethi %hi(_C_LABEL(kernel_top) - KERNBASE), %l3 ! and store it |
st %o4, [%l3 + %lo(_C_LABEL(esym) - KERNBASE)] |
st %o4, [%l3 + %lo(_C_LABEL(kernel_top) - KERNBASE)] |
|
b,a 4f |
3: |
3: |
#endif |
#endif |
/* |
/* |
|
* The boot loader did not pass in a value for `kernel_top'; |
|
* let it default to `end'. |
|
*/ |
|
set end, %o4 |
|
sethi %hi(_C_LABEL(kernel_top) - KERNBASE), %l3 ! store kernel_top |
|
st %o4, [%l3 + %lo(_C_LABEL(kernel_top) - KERNBASE)] |
|
|
|
4: |
|
|
|
/* |
* Sun4 passes in the `load address'. Although possible, its highly |
* Sun4 passes in the `load address'. Although possible, its highly |
* unlikely that OpenBoot would place the prom vector there. |
* unlikely that OpenBoot would place the prom vector there. |
*/ |
*/ |
|
|
be is_sun4 |
be is_sun4 |
nop |
nop |
|
|
#if defined(SUN4C) || defined(SUN4M) |
#if defined(SUN4C) || defined(SUN4M) || defined(SUN4D) |
/* |
/* |
* Be prepared to get OF client entry in either %o0 or %o3. |
* Be prepared to get OF client entry in either %o0 or %o3. |
|
* XXX Will this ever trip on sun4d? Let's hope not! |
*/ |
*/ |
cmp %o0, 0 |
cmp %o0, 0 |
be is_openfirm |
be is_openfirm |
|
|
nop ! } |
nop ! } |
|
|
/* |
/* |
* are we on a sun4c or a sun4m? |
* are we on a sun4c or a sun4m or a sun4d? |
*/ |
*/ |
ld [%g7 + PV_NODEOPS], %o4 ! node = pv->pv_nodeops->no_nextnode(0) |
ld [%g7 + PV_NODEOPS], %o4 ! node = pv->pv_nodeops->no_nextnode(0) |
ld [%o4 + NO_NEXTNODE], %o4 |
ld [%o4 + NO_NEXTNODE], %o4 |
|
|
cmp %o0, 'm' |
cmp %o0, 'm' |
be is_sun4m |
be is_sun4m |
nop |
nop |
#endif /* SUN4C || SUN4M */ |
cmp %o0, 'd' |
|
be is_sun4d |
|
nop |
|
#endif /* SUN4C || SUN4M || SUN4D */ |
|
|
! ``on a sun4d?! hell no!'' |
/* |
|
* Don't know what type of machine this is; just halt back |
|
* out to the PROM. |
|
*/ |
ld [%g7 + PV_HALT], %o1 ! by this kernel, then halt |
ld [%g7 + PV_HALT], %o1 ! by this kernel, then halt |
call %o1 |
call %o1 |
nop |
nop |
|
|
nop |
nop |
/*NOTREACHED*/ |
/*NOTREACHED*/ |
#endif |
#endif |
|
is_sun4d: |
|
#if defined(SUN4D) |
|
set trapbase_sun4m, %g6 /* XXXJRT trapbase_sun4d */ |
|
mov SUN4CM_PGSHIFT, %g5 |
|
b start_havetype |
|
mov CPU_SUN4D, %g4 |
|
#else |
|
set sun4d_notsup-KERNBASE, %o0 |
|
ld [%g7 + PV_EVAL], %o1 |
|
call %o1 ! print a message saying that the |
|
nop ! sun4d architecture is not supported |
|
ld [%g7 + PV_HALT], %o1 ! by this kernel, then halt |
|
call %o1 |
|
nop |
|
/*NOTREACHED*/ |
|
#endif |
is_sun4c: |
is_sun4c: |
#if defined(SUN4C) |
#if defined(SUN4C) |
set trapbase_sun4c, %g6 |
set trapbase_sun4c, %g6 |
Line 3607 start_havetype: |
|
Line 3662 start_havetype: |
|
*/ |
*/ |
clr %l0 ! lowva |
clr %l0 ! lowva |
set KERNBASE, %l1 ! highva |
set KERNBASE, %l1 ! highva |
set _end + (2 << 18), %l2 ! last va that must be remapped |
|
#ifdef DDB |
sethi %hi(_C_LABEL(kernel_top) - KERNBASE), %o0 |
sethi %hi(_C_LABEL(esym) - KERNBASE), %o1 |
ld [%o0 + %lo(_C_LABEL(kernel_top) - KERNBASE)], %o1 |
ld [%o1+%lo(_C_LABEL(esym) - KERNBASE)], %o1 |
set (2 << 18), %o2 ! add slack for sun4c MMU |
tst %o1 |
add %o1, %o2, %l2 ! last va that must be remapped |
bz 1f |
|
nop |
|
set (2 << 18), %l2 |
|
add %l2, %o1, %l2 ! last va that must be remapped |
|
1: |
|
#endif |
|
/* |
/* |
* Need different initial mapping functions for different |
* Need different initial mapping functions for different |
* types of machines. |
* types of machines. |
|
|
2: |
2: |
#endif /* SUN4 */ |
#endif /* SUN4 */ |
|
|
#if defined(SUN4M) |
#if defined(SUN4M) || defined(SUN4D) |
cmp %g4, CPU_SUN4M ! skip for sun4m! |
cmp %g4, CPU_SUN4M |
bne 3f |
beq 3f |
|
nop |
|
cmp %g4, CPU_SUN4D |
|
bne 4f |
|
|
|
3: |
/* |
/* |
* The OBP guarantees us a 16MB mapping using a level 1 PTE at |
* The OBP guarantees us a 16MB mapping using a level 1 PTE at |
* the start of the memory bank in which we were loaded. All we |
* the start of the memory bank in which we were loaded. All we |
|
|
sta %l4, [%o1] ASI_BYPASS |
sta %l4, [%o1] ASI_BYPASS |
!b,a startmap_done |
!b,a startmap_done |
|
|
3: |
4: |
#endif /* SUN4M */ |
#endif /* SUN4M || SUN4D */ |
! botch! We should blow up. |
! botch! We should blow up. |
|
|
startmap_done: |
startmap_done: |
|
|
1: |
1: |
#endif |
#endif |
|
|
#if ((defined(SUN4) || defined(SUN4C)) && defined(SUN4M)) |
#if (defined(SUN4) || defined(SUN4C)) && (defined(SUN4M) || defined(SUN4D)) |
|
|
/* |
/* |
* Patch instructions at specified labels that start |
* Patch instructions at specified labels that start |
|
|
ld [%o0 + %lo(Lgandul)], %l0 ! %l0 = NOP |
ld [%o0 + %lo(Lgandul)], %l0 ! %l0 = NOP |
|
|
cmp %g4, CPU_SUN4M |
cmp %g4, CPU_SUN4M |
|
beq,a 2f |
|
nop |
|
|
|
cmp %g4, CPU_SUN4D |
bne,a 1f |
bne,a 1f |
nop |
nop |
|
|
! this should be automated! |
2: ! this should be automated! |
MUNGE(NOP_ON_4M_1) |
MUNGE(NOP_ON_4M_1) |
MUNGE(NOP_ON_4M_2) |
MUNGE(NOP_ON_4M_2) |
MUNGE(NOP_ON_4M_3) |
MUNGE(NOP_ON_4M_3) |
|
|
MUNGE(NOP_ON_4M_12) |
MUNGE(NOP_ON_4M_12) |
MUNGE(NOP_ON_4M_13) |
MUNGE(NOP_ON_4M_13) |
MUNGE(NOP_ON_4M_14) |
MUNGE(NOP_ON_4M_14) |
|
MUNGE(NOP_ON_4M_15) |
b,a 2f |
b,a 2f |
|
|
1: |
1: |
Line 3996 _C_LABEL(cpu_hatch): |
|
Line 4055 _C_LABEL(cpu_hatch): |
|
set _C_LABEL(proc0), %g3 ! p = proc0 |
set _C_LABEL(proc0), %g3 ! p = proc0 |
sethi %hi(_C_LABEL(sched_whichqs)), %g2 |
sethi %hi(_C_LABEL(sched_whichqs)), %g2 |
sethi %hi(cpcb), %g6 |
sethi %hi(cpcb), %g6 |
sethi %hi(curproc), %g7 |
sethi %hi(curlwp), %g7 |
st %g0, [%g7 + %lo(curproc)] ! curproc = NULL; |
st %g0, [%g7 + %lo(curlwp)] ! curlwp = NULL; |
|
|
mov PSR_S|PSR_ET, %g1 ! oldpsr = PSR_S | PSR_ET; |
mov PSR_S|PSR_ET, %g1 ! oldpsr = PSR_S | PSR_ET; |
sethi %hi(IDLE_UP), %g5 |
sethi %hi(IDLE_UP), %g5 |
Line 4029 _C_LABEL(cpu_hatch): |
|
Line 4088 _C_LABEL(cpu_hatch): |
|
#include "sigcode_state.s" |
#include "sigcode_state.s" |
|
|
.globl _C_LABEL(sigcode) |
.globl _C_LABEL(sigcode) |
|
.globl _C_LABEL(upcallcode) |
.globl _C_LABEL(esigcode) |
.globl _C_LABEL(esigcode) |
_C_LABEL(sigcode): |
_C_LABEL(sigcode): |
|
|
Line 4048 _C_LABEL(sigcode): |
|
Line 4108 _C_LABEL(sigcode): |
|
! sigreturn does not return unless it fails |
! sigreturn does not return unless it fails |
mov SYS_exit, %g1 ! exit(errno) |
mov SYS_exit, %g1 ! exit(errno) |
t ST_SYSCALL |
t ST_SYSCALL |
|
_C_LABEL(upcallcode): |
|
! not yet implemented |
|
mov 101, %o0 |
|
mov SYS_exit, %g1 ! exit(101) |
|
t ST_SYSCALL |
_C_LABEL(esigcode): |
_C_LABEL(esigcode): |
|
|
/* |
/* |
Line 4300 ENTRY(write_user_windows) |
|
Line 4365 ENTRY(write_user_windows) |
|
* %g4 = lastproc |
* %g4 = lastproc |
* %g5 = <free>; newpcb |
* %g5 = <free>; newpcb |
* %g6 = %hi(cpcb) |
* %g6 = %hi(cpcb) |
* %g7 = %hi(curproc) |
* %g7 = %hi(curlwp) |
* %o0 = tmp 1 |
* %o0 = tmp 1 |
* %o1 = tmp 2 |
* %o1 = tmp 2 |
* %o2 = tmp 3 |
* %o2 = tmp 3 |
Line 4336 ENTRY(write_user_windows) |
|
Line 4401 ENTRY(write_user_windows) |
|
/* |
/* |
* switchexit is called only from cpu_exit() before the current process |
* switchexit is called only from cpu_exit() before the current process |
* has freed its vmspace and kernel stack; we must schedule them to be |
* has freed its vmspace and kernel stack; we must schedule them to be |
* freed. (curproc is already NULL.) |
* freed. (curlwp is already NULL.) |
* |
* |
* We lay the process to rest by changing to the `idle' kernel stack, |
* We lay the process to rest by changing to the `idle' kernel stack, |
* and note that the `last loaded process' is nonexistent. |
* and note that the `last loaded process' is nonexistent. |
*/ |
*/ |
|
ENTRY(switchlwpexit) |
|
!!Hmm, switchexit() might as well have passed us the `exit2' function to call. |
|
set _C_LABEL(lwp_exit2), %g1 |
|
b,a switchexit0 |
ENTRY(switchexit) |
ENTRY(switchexit) |
|
set _C_LABEL(exit2), %g1 |
|
switchexit0: |
mov %o0, %g2 ! save proc for exit2() call |
mov %o0, %g2 ! save proc for exit2() call |
|
|
/* |
/* |
Line 4376 ENTRY(switchexit) |
|
Line 4447 ENTRY(switchexit) |
|
#endif |
#endif |
|
|
wr %g0, PSR_S|PSR_ET, %psr ! and then enable traps |
wr %g0, PSR_S|PSR_ET, %psr ! and then enable traps |
call _C_LABEL(exit2) ! exit2(p) |
call %g1 ! {lwp}exit2(p) |
mov %g2, %o0 |
mov %g2, %o0 |
|
|
/* |
/* |
Line 4389 ENTRY(switchexit) |
|
Line 4460 ENTRY(switchexit) |
|
* %g2 = %hi(whichqs) |
* %g2 = %hi(whichqs) |
* %g4 = lastproc |
* %g4 = lastproc |
* %g6 = %hi(cpcb) |
* %g6 = %hi(cpcb) |
* %g7 = %hi(curproc) |
* %g7 = %hi(curlwp) |
* %o0 = tmp 1 |
* %o0 = tmp 1 |
* %o1 = tmp 2 |
* %o1 = tmp 2 |
* %o3 = whichqs |
* %o3 = whichqs |
Line 4402 ENTRY(switchexit) |
|
Line 4473 ENTRY(switchexit) |
|
sethi %hi(_C_LABEL(sched_whichqs)), %g2 |
sethi %hi(_C_LABEL(sched_whichqs)), %g2 |
clr %g4 ! lastproc = NULL; |
clr %g4 ! lastproc = NULL; |
sethi %hi(cpcb), %g6 |
sethi %hi(cpcb), %g6 |
sethi %hi(curproc), %g7 |
sethi %hi(curlwp), %g7 |
st %g0, [%g7 + %lo(curproc)] ! curproc = NULL; |
st %g0, [%g7 + %lo(curlwp)] ! curlwp = NULL; |
b,a idle_enter_no_schedlock |
b,a idle_enter_no_schedlock |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
|
|
|
|
#endif |
#endif |
|
|
idle_enter_no_schedlock: |
idle_enter_no_schedlock: |
wr %g1, 0, %psr ! (void) spl0(); |
wr %g1, 0, %psr ! spl0(); |
1: ! spin reading whichqs until nonzero |
1: ! spin reading whichqs until nonzero |
ld [%g2 + %lo(_C_LABEL(sched_whichqs))], %o3 |
ld [%g2 + %lo(_C_LABEL(sched_whichqs))], %o3 |
tst %o3 |
tst %o3 |
Line 4459 idle_enter_no_schedlock: |
|
Line 4530 idle_enter_no_schedlock: |
|
#else |
#else |
bnz,a Lsw_scan |
bnz,a Lsw_scan |
#endif |
#endif |
|
! NB: annulled delay slot (executed when we leave the idle loop) |
wr %g1, PSR_PIL, %psr ! (void) splhigh(); |
wr %g1, PSR_PIL, %psr ! (void) splhigh(); |
|
|
! Check uvm.page_idle_zero |
! Check uvm.page_idle_zero |
Line 4474 idle_enter_no_schedlock: |
|
Line 4546 idle_enter_no_schedlock: |
|
#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) |
#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) |
idle_leave: |
idle_leave: |
/* Before we leave the idle loop, detain the scheduler lock */ |
/* Before we leave the idle loop, detain the scheduler lock */ |
nop;nop;nop; ! just wrote to %psr; delay before doing a `save' |
nop;nop;nop; /* just wrote to %psr; delay before doing a `save' */ |
SAVE_GLOBALS_AND_CALL(sched_lock_idle) |
SAVE_GLOBALS_AND_CALL(sched_lock_idle) |
b,a Lsw_scan |
b,a Lsw_scan |
#endif |
#endif |
Line 4519 ENTRY(cpu_switch) |
|
Line 4591 ENTRY(cpu_switch) |
|
* %g4 = lastproc |
* %g4 = lastproc |
* %g5 = tmp 0 |
* %g5 = tmp 0 |
* %g6 = %hi(cpcb) |
* %g6 = %hi(cpcb) |
* %g7 = %hi(curproc) |
* %g7 = %hi(curlwp) |
* %o0 = tmp 1 |
* %o0 = tmp 1 |
* %o1 = tmp 2 |
* %o1 = tmp 2 |
* %o2 = tmp 3 |
* %o2 = tmp 3 |
Line 4535 ENTRY(cpu_switch) |
|
Line 4607 ENTRY(cpu_switch) |
|
rd %psr, %g1 ! oldpsr = %psr; |
rd %psr, %g1 ! oldpsr = %psr; |
st %g1, [%o0 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; |
st %g1, [%o0 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; |
andn %g1, PSR_PIL, %g1 ! oldpsr &= ~PSR_PIL; |
andn %g1, PSR_PIL, %g1 ! oldpsr &= ~PSR_PIL; |
sethi %hi(curproc), %g7 |
sethi %hi(curlwp), %g7 |
st %g0, [%g7 + %lo(curproc)] ! curproc = NULL; |
st %g0, [%g7 + %lo(curlwp)] ! curlwp = NULL; |
|
|
Lsw_scan: |
Lsw_scan: |
nop; nop; nop ! paranoia |
nop; nop; nop ! paranoia |
|
|
sll %o4, 3, %o0 |
sll %o4, 3, %o0 |
add %o0, %o5, %o5 |
add %o0, %o5, %o5 |
ld [%o5], %g3 ! p = q->ph_link; |
ld [%o5], %g3 ! p = q->ph_link; |
|
|
|
cpu_switch0: |
|
/* |
|
* Here code in common with cpu_preempt() starts. |
|
* cpu_preempt() sets %g3 to p, and %o5 to p->p_back, |
|
* so the following will unlink p from the switch_qs list. |
|
*/ |
cmp %g3, %o5 ! if (p == q) |
cmp %g3, %o5 ! if (p == q) |
be Lsw_panic_rq ! panic("switch rq"); |
be Lsw_panic_rq ! panic("switch rq"); |
EMPTY |
EMPTY |
|
|
* %g4 = lastproc |
* %g4 = lastproc |
* %g5 = newpcb |
* %g5 = newpcb |
* %g6 = %hi(cpcb) |
* %g6 = %hi(cpcb) |
* %g7 = %hi(curproc) |
* %g7 = %hi(curlwp) |
* %o0 = tmp 1 |
* %o0 = tmp 1 |
* %o1 = tmp 2 |
* %o1 = tmp 2 |
* %o2 = tmp 3 |
* %o2 = tmp 3 |
|
|
*/ |
*/ |
|
|
/* firewalls */ |
/* firewalls */ |
ld [%g3 + P_WCHAN], %o0 ! if (p->p_wchan) |
ld [%g3 + L_WCHAN], %o0 ! if (p->p_wchan) |
tst %o0 |
tst %o0 |
bne Lsw_panic_wchan ! panic("switch wchan"); |
bne Lsw_panic_wchan ! panic("switch wchan"); |
EMPTY |
EMPTY |
ldsb [%g3 + P_STAT], %o0 ! if (p->p_stat != SRUN) |
ld [%g3 + L_STAT], %o0 ! if (p->p_stat != SRUN) |
cmp %o0, SRUN |
cmp %o0, LSRUN |
bne Lsw_panic_srun ! panic("switch SRUN"); |
bne Lsw_panic_srun ! panic("switch SRUN"); |
EMPTY |
EMPTY |
|
|
|
|
* Committed to running process p. |
* Committed to running process p. |
* It may be the same as the one we were running before. |
* It may be the same as the one we were running before. |
*/ |
*/ |
mov SONPROC, %o0 ! p->p_stat = SONPROC; |
mov LSONPROC, %o0 ! p->p_stat = LSONPROC; |
stb %o0, [%g3 + P_STAT] |
st %o0, [%g3 + L_STAT] |
|
|
/* p->p_cpu initialized in fork1() for single-processor */ |
/* p->p_cpu initialized in fork1() for single-processor */ |
#if defined(MULTIPROCESSOR) |
#if defined(MULTIPROCESSOR) |
sethi %hi(_CISELFP), %o0 ! p->p_cpu = cpuinfo.ci_self; |
sethi %hi(_CISELFP), %o0 ! p->p_cpu = cpuinfo.ci_self; |
ld [%o0 + %lo(_CISELFP)], %o0 |
ld [%o0 + %lo(_CISELFP)], %o0 |
st %o0, [%g3 + P_CPU] |
st %o0, [%g3 + L_CPU] |
#endif |
#endif |
|
|
sethi %hi(_C_LABEL(want_resched)), %o0 ! want_resched = 0; |
sethi %hi(_C_LABEL(want_resched)), %o0 ! want_resched = 0; |
|
|
/* Done with the run queues; release the scheduler lock */ |
/* Done with the run queues; release the scheduler lock */ |
SAVE_GLOBALS_AND_CALL(sched_unlock_idle) |
SAVE_GLOBALS_AND_CALL(sched_unlock_idle) |
#endif |
#endif |
ld [%g3 + P_ADDR], %g5 ! newpcb = p->p_addr; |
ld [%g3 + L_ADDR], %g5 ! newpcb = p->p_addr; |
st %g0, [%g3 + 4] ! p->p_back = NULL; |
st %g0, [%g3 + 4] ! p->p_back = NULL; |
ld [%g5 + PCB_PSR], %g2 ! newpsr = newpcb->pcb_psr; |
ld [%g5 + PCB_PSR], %g2 ! newpsr = newpcb->pcb_psr; |
st %g3, [%g7 + %lo(curproc)] ! curproc = p; |
st %g3, [%g7 + %lo(curlwp)] ! curlwp = p; |
|
|
cmp %g3, %g4 ! p == lastproc? |
cmp %g3, %g4 ! p == lastproc? |
be,a Lsw_sameproc ! yes, go return 0 |
be,a Lsw_sameproc ! yes, go return 0 |
|
|
* can talk about user space stuff. (Its pcb_uw is currently |
* can talk about user space stuff. (Its pcb_uw is currently |
* zero so it is safe to have interrupts going here.) |
* zero so it is safe to have interrupts going here.) |
*/ |
*/ |
ld [%g3 + P_VMSPACE], %o3 ! vm = p->p_vmspace; |
mov 1, %o0 ! return value |
|
ld [%g3 + L_PROC], %o3 ! p = l->l_proc; |
|
ld [%o3 + P_VMSPACE], %o3 ! vm = p->p_vmspace; |
ld [%o3 + VM_PMAP], %o3 ! pm = vm->vm_map.vm_pmap; |
ld [%o3 + VM_PMAP], %o3 ! pm = vm->vm_map.vm_pmap; |
ld [%o3 + PMAP_CTX], %o0 ! if (pm->pm_ctx != NULL) |
ld [%o3 + PMAP_CTX], %o1 ! if (pm->pm_ctx != NULL) |
tst %o0 |
tst %o1 |
bnz,a Lsw_havectx ! goto havecontext; |
bnz,a Lsw_havectx ! goto havecontext; |
ld [%o3 + PMAP_CTXNUM], %o0 ! load context number |
ld [%o3 + PMAP_CTXNUM], %o1 ! load context number |
|
|
/* p does not have a context: call ctx_alloc to get one */ |
/* p does not have a context: call ctx_alloc to get one */ |
save %sp, -CCFSZ, %sp |
save %sp, -CCFSZ, %sp |
|
|
mov %i3, %o0 |
mov %i3, %o0 |
|
|
ret |
ret |
restore |
restore %g0, 1, %o0 ! set return value to 1 |
|
|
/* p does have a context: just switch to it */ |
/* p does have a context: just switch to it */ |
Lsw_havectx: |
Lsw_havectx: |
! context is in %o0 |
! context is in %o1 |
! pmap is in %o3 |
|
#if (defined(SUN4) || defined(SUN4C)) && defined(SUN4M) |
#if (defined(SUN4) || defined(SUN4C)) && defined(SUN4M) |
sethi %hi(_C_LABEL(cputyp)), %o1 ! what cpu are we running on? |
NOP_ON_4M_15: |
ld [%o1 + %lo(_C_LABEL(cputyp))], %o1 |
b,a 1f |
cmp %o1, CPU_SUN4M |
b,a 2f |
be 1f |
|
nop |
|
#endif |
#endif |
|
1: |
#if defined(SUN4) || defined(SUN4C) |
#if defined(SUN4) || defined(SUN4C) |
set AC_CONTEXT, %o1 |
set AC_CONTEXT, %o2 |
retl |
retl |
stba %o0, [%o1] ASI_CONTROL ! setcontext(vm->vm_pmap.pm_ctxnum); |
stba %o1, [%o2] ASI_CONTROL ! setcontext(vm->vm_pmap.pm_ctxnum); |
#endif |
#endif |
1: |
2: |
#if defined(SUN4M) |
#if defined(SUN4M) |
/* |
/* |
* Flush caches that need to be flushed on context switch. |
* Flush caches that need to be flushed on context switch. |
|
|
set CPUINFO_VA+CPUINFO_PURE_VCACHE_FLS, %o2 |
set CPUINFO_VA+CPUINFO_PURE_VCACHE_FLS, %o2 |
ld [%o2], %o2 |
ld [%o2], %o2 |
mov %o7, %g7 ! save return address |
mov %o7, %g7 ! save return address |
jmpl %o2, %o7 ! this function must not clobber %o0 and %g7 |
jmpl %o2, %o7 ! this function must not clobber %o0,%o1 and %g7 |
nop |
nop |
|
|
set SRMMU_CXR, %o1 |
set SRMMU_CXR, %o2 |
jmp %g7 + 8 |
jmp %g7 + 8 |
sta %o0, [%o1] ASI_SRMMU ! setcontext(vm->vm_pmap.pm_ctxnum); |
sta %o1, [%o2] ASI_SRMMU ! setcontext(vm->vm_pmap.pm_ctxnum); |
#endif |
#endif |
|
|
Lsw_sameproc: |
Lsw_sameproc: |
|
|
! wr %g2, 0 %psr ! %psr = newpsr; (done earlier) |
! wr %g2, 0 %psr ! %psr = newpsr; (done earlier) |
nop |
nop |
retl |
retl |
nop |
mov %g0, %o0 ! return value = 0 |
|
|
|
ENTRY(cpu_preempt) |
|
/* |
|
* Like cpu_switch, but we're passed the process to switch to. |
|
* |
|
* Use the same register usage convention as in cpu_switch(). |
|
*/ |
|
mov %o0, %g4 ! lastproc = arg1; |
|
mov %o1, %g3 ! newproc = arg2; |
|
sethi %hi(_C_LABEL(sched_whichqs)), %g2 ! set up addr regs |
|
sethi %hi(cpcb), %g6 |
|
ld [%g6 + %lo(cpcb)], %o0 |
|
std %o6, [%o0 + PCB_SP] ! cpcb->pcb_<sp,pc> = <sp,pc>; |
|
rd %psr, %g1 ! oldpsr = %psr; |
|
st %g1, [%o0 + PCB_PSR] ! cpcb->pcb_psr = oldpsr; |
|
andn %g1, PSR_PIL, %g1 ! oldpsr &= ~PSR_PIL; |
|
sethi %hi(curlwp), %g7 |
|
st %g0, [%g7 + %lo(curlwp)] ! curlwp = NULL; |
|
|
|
/* |
|
* now set up %o4 (which) and %o5 (p->p_back), and continue with |
|
* common code in cpu_switch(). |
|
*/ |
|
ld [%g3 + L_PRIORITY], %o4 |
|
srl %o4, 2, %o4 |
|
ld [%g3 + 4], %o5 ! %o5 = p->p_back |
|
b,a cpu_switch0 |
|
|
/* |
/* |
* Snapshot the current process so that stack frames are up to date. |
* Snapshot the current process so that stack frames are up to date. |
Line 4823 ENTRY(proc_trampoline) |
|
Line 4928 ENTRY(proc_trampoline) |
|
mov %l1, %o0 |
mov %l1, %o0 |
|
|
/* |
/* |
* Here we finish up as in syscall, but simplified. We need to |
* Here we finish up as in syscall, but simplified. |
* fiddle pc and npc a bit, as execve() / setregs() will have |
* cpu_fork() or sendsig() (if we took a pending signal |
* set npc only, anticipating that trap.c will advance past the |
* in child_return()) will have set the user-space return |
* trap instruction; but we bypass that, so we must do it manually. |
* address in tf_pc. In both cases, %npc should be %pc + 4. |
*/ |
*/ |
mov PSR_S, %l0 ! user psr (no need to load it) |
mov PSR_S, %l0 ! user psr (no need to load it) |
!?wr %g0, 2, %wim ! %wim = 2 |
!?wr %g0, 2, %wim ! %wim = 2 |
ld [%sp + CCFSZ + 8], %l1 ! pc = tf->tf_npc from execve/fork |
ld [%sp + CCFSZ + 4], %l1 ! pc = tf->tf_pc from cpu_fork() |
b return_from_syscall |
b return_from_syscall |
add %l1, 4, %l2 ! npc = pc+4 |
add %l1, 4, %l2 ! npc = pc+4 |
|
|
Line 5834 ENTRY(ienab_bic) |
|
Line 5939 ENTRY(ienab_bic) |
|
* raise(cpu, level) |
* raise(cpu, level) |
*/ |
*/ |
ENTRY(raise) |
ENTRY(raise) |
|
#if !defined(MSIIEP) /* normal suns */ |
! *(ICR_PI_SET + cpu*_MAXNBPG) = PINTR_SINTRLEV(level) |
! *(ICR_PI_SET + cpu*_MAXNBPG) = PINTR_SINTRLEV(level) |
sethi %hi(1 << 16), %o2 |
sethi %hi(1 << 16), %o2 |
sll %o2, %o1, %o2 |
sll %o2, %o1, %o2 |
|
|
add %o1, %o3, %o1 |
add %o1, %o3, %o1 |
retl |
retl |
st %o2, [%o1] |
st %o2, [%o1] |
|
#else /* MSIIEP - ignore %o0, only one cpu ever */ |
|
mov 1, %o2 |
|
sethi %hi(MSIIEP_PCIC_VA), %o0 |
|
sll %o2, %o1, %o2 |
|
retl |
|
sth %o2, [%o0 + PCIC_SOFT_INTR_SET_REG] |
|
#endif |
|
|
/* |
/* |
* Read Synchronous Fault Status registers. |
* Read Synchronous Fault Status registers. |
Line 5951 _ENTRY(_C_LABEL(hypersparc_pure_vcache_f |
|
Line 6063 _ENTRY(_C_LABEL(hypersparc_pure_vcache_f |
|
|
|
#endif /* SUN4M */ |
#endif /* SUN4M */ |
|
|
|
#if !defined(MSIIEP) /* normal suns */ |
/* |
/* |
* void lo_microtime(struct timeval *tv) |
* void lo_microtime(struct timeval *tv) |
* |
* |
|
|
set 1000000, %g5 ! normalize usec value |
set 1000000, %g5 ! normalize usec value |
cmp %o3, %g5 |
cmp %o3, %g5 |
bl,a 4f |
bl,a 4f |
st %o2, [%o0] ! (should be able to std here) |
st %o2, [%o0] |
add %o2, 1, %o2 ! overflow |
add %o2, 1, %o2 ! overflow |
sub %o3, %g5, %o3 |
sub %o3, %g5, %o3 |
st %o2, [%o0] ! (should be able to std here) |
st %o2, [%o0] |
4: |
4: |
retl |
retl |
st %o3, [%o0+4] |
st %o3, [%o0+4] |
|
|
|
#else /* MSIIEP */ |
|
/* XXX: uwe: can be merged with 4c/4m version above */ |
|
/* |
|
* ms-IIep version of |
|
* void microtime(struct timeval *tv) |
|
* |
|
* This is similar to 4c/4m microtime. The difference is that |
|
* counter uses 31 bits and ticks every 4 CPU cycles (cpu is @100MHz) |
|
* the magic to divide by 25 is stolen from gcc |
|
*/ |
|
ENTRY(microtime) |
|
sethi %hi(_C_LABEL(time)), %g2 |
|
|
|
sethi %hi(MSIIEP_PCIC_VA), %g3 |
|
or %g3, PCIC_SCCR_REG, %g3 |
|
|
|
2: |
|
ldd [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec |
|
ld [%g3], %o4 ! system (timer) counter |
|
ldd [%g2+%lo(_C_LABEL(time))], %g4 ! see if time values changed |
|
cmp %g4, %o2 |
|
bne 2b ! if time.tv_sec changed |
|
cmp %g5, %o3 |
|
bne 2b ! if time.tv_usec changed |
|
tst %o4 |
|
!! %o2 - time.tv_sec; %o3 - time.tv_usec; %o4 - timer counter |
|
|
|
!!! BEGIN ms-IIep specific code |
|
bpos 3f ! if limit not reached yet |
|
clr %g4 ! then use timer as is |
|
|
|
set 0x80000000, %g5 |
|
sethi %hi(_C_LABEL(tick)), %g4 |
|
bclr %g5, %o4 ! cleat limit reached flag |
|
ld [%g4+%lo(_C_LABEL(tick))], %g4 |
|
|
|
!! %g4 - either 0 or tick (if timer has hit the limit) |
|
3: |
|
inc -1, %o4 ! timer is 1-based, adjust |
|
!! divide by 25 magic stolen from a gcc output |
|
set 1374389535, %g5 |
|
umul %o4, %g5, %g0 |
|
rd %y, %o4 |
|
srl %o4, 3, %o4 |
|
add %o4, %g4, %o4 ! may be bump usec by tick |
|
!!! END ms-IIep specific code |
|
|
|
add %o3, %o4, %o3 ! add timer to time.tv_usec |
|
set 1000000, %g5 ! normalize usec value |
|
cmp %o3, %g5 |
|
bl,a 4f |
|
st %o2, [%o0] |
|
inc %o2 ! overflow into tv_sec |
|
sub %o3, %g5, %o3 |
|
st %o2, [%o0] |
|
4: retl |
|
st %o3, [%o0 + 4] |
|
#endif /* MSIIEP */ |
|
|
/* |
/* |
* delay function |
* delay function |
* |
* |
|
|
mov %g6, %o0 |
mov %g6, %o0 |
|
|
.data |
.data |
#ifdef DDB |
.globl _C_LABEL(kernel_top) |
.globl _C_LABEL(esym) |
_C_LABEL(kernel_top): |
_C_LABEL(esym): |
|
.word 0 |
.word 0 |
#endif |
|
.globl _C_LABEL(bootinfo) |
.globl _C_LABEL(bootinfo) |
_C_LABEL(bootinfo): |
_C_LABEL(bootinfo): |
.word 0 |
.word 0 |