diff --git a/sys/alpha/alpha/exception.s b/sys/alpha/alpha/exception.s index bc8ee5730df..b3bf1dceab4 100644 --- a/sys/alpha/alpha/exception.s +++ b/sys/alpha/alpha/exception.s @@ -140,16 +140,19 @@ XentSys1: LDGP(pv) beq t1, exception_return /* set the hae register if this process has specified a value */ - ldq t0, GD_CURPROC(globalp) - beq t0, 3f - ldq t1, P_MD_FLAGS(t0) + ldq s0, GD_CURPROC(globalp) + ldq t1, P_MD_FLAGS(s0) and t1, MDP_HAEUSED beq t1, 3f - ldq a0, P_MD_HAE(t0) + ldq a0, P_MD_HAE(s0) ldq pv, chipset + CHIPSET_WRITE_HAE CALL((pv)) 3: - +#ifdef SMP + /* leave the kernel */ + stl zero, P_MD_KERNNEST(s0) +#endif + /* restore the registers, and return */ ldq v0,(FRAME_V0*8)(sp) ldq s0,(FRAME_S0*8)(sp) @@ -253,28 +256,42 @@ LEAF(exception_return, 1) /* XXX should be NESTED */ br pv, Ler1 Ler1: LDGP(pv) - ldq s1, (FRAME_PS * 8)(sp) /* get the saved PS */ - and s1, ALPHA_PSL_IPL_MASK, t0 /* look at the saved IPL */ - bne t0, Lrestoreregs /* != 0: can't do AST or SIR */ + ldq s0, GD_CURPROC(globalp) /* save curproc in s0 */ +#ifdef SMP + ldl s1, P_MD_KERNNEST(s0) + subl s1, 1, s1 /* decrement nesting level */ +#endif - and s1, ALPHA_PSL_USERMODE, t0 /* are we returning to user? */ - beq t0, Lrestoreregs /* no: just return */ + ldq t1, (FRAME_PS * 8)(sp) /* get the saved PS */ + and t1, ALPHA_PSL_USERMODE, t0 /* are we returning to user? */ + beq t0, Lkernelret /* no: kernel return */ /* Handle any AST's or resched's. */ mov sp, a0 /* only arg is frame */ CALL(ast) +#ifdef SMP + br Lrestoreregs +#endif + +Lkernelret: +#ifdef SMP + beq s1, Lrestoreregs + stq globalp, (FRAME_T7*8)(sp) /* fixup globalp */ +#endif Lrestoreregs: /* set the hae register if this process has specified a value */ - ldq t0, GD_CURPROC(globalp) - beq t0, Lnohae - ldq t1, P_MD_FLAGS(t0) + ldq t1, P_MD_FLAGS(s0) and t1, MDP_HAEUSED beq t1, Lnohae ldq a0, P_MD_HAE(t0) ldq pv, chipset + CHIPSET_WRITE_HAE CALL((pv)) Lnohae: +#ifdef SMP + /* leave the kernel */ + stl s1, P_MD_KERNNEST(s0) +#endif /* restore the registers, and return */ bsr ra, exception_restore_regs /* jmp/CALL trashes pv/t12 */ diff --git a/sys/alpha/alpha/genassym.c b/sys/alpha/alpha/genassym.c index 51046549ce3..03990ea51b3 100644 --- a/sys/alpha/alpha/genassym.c +++ b/sys/alpha/alpha/genassym.c @@ -84,6 +84,9 @@ ASSYM(P_ADDR, offsetof(struct proc, p_addr)); ASSYM(P_MD_FLAGS, offsetof(struct proc, p_md.md_flags)); ASSYM(P_MD_PCBPADDR, offsetof(struct proc, p_md.md_pcbpaddr)); ASSYM(P_MD_HAE, offsetof(struct proc, p_md.md_hae)); +#ifdef SMP +ASSYM(P_MD_KERNNEST, offsetof(struct proc, p_md.md_kernnest)); +#endif ASSYM(MDP_HAEUSED, MDP_HAEUSED); ASSYM(CHIPSET_WRITE_HAE, offsetof(struct alpha_chipset, write_hae)); diff --git a/sys/alpha/alpha/interrupt.c b/sys/alpha/alpha/interrupt.c index c44eccf3b13..346b21cd544 100644 --- a/sys/alpha/alpha/interrupt.c +++ b/sys/alpha/alpha/interrupt.c @@ -91,12 +91,22 @@ interrupt(a0, a1, a2, framep) struct trapframe *framep; { struct proc *p; +#ifdef SMP + critical_t s; +#endif /* * Find our per-cpu globals. */ +#ifdef SMP + s = critical_enter(); +#endif globalp = (struct globaldata *) alpha_pal_rdval(); p = curproc; +#ifdef SMP + p->p_md.md_kernnest++; + critical_exit(s); +#endif atomic_add_int(&p->p_intr_nesting_level, 1); #ifndef SMP { diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index 78036218e1d..f6236690593 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -966,6 +966,9 @@ alpha_init(pfn, ptb, bim, bip, biv) globaldata_init(globalp, alpha_pal_whami(), sz); alpha_pal_wrval((u_int64_t) globalp); PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */ +#ifdef SMP + proc0.p_md.md_kernnest = 1; +#endif } /* diff --git a/sys/alpha/alpha/trap.c b/sys/alpha/alpha/trap.c index 1b08a7d128b..228c50b81bb 100644 --- a/sys/alpha/alpha/trap.c +++ b/sys/alpha/alpha/trap.c @@ -312,14 +312,24 @@ trap(a0, a1, a2, entry, framep) u_int64_t ucode; u_quad_t sticks; int user; +#ifdef SMP + critical_t s; +#endif /* * Find our per-cpu globals. */ +#ifdef SMP + s = critical_enter(); +#endif globalp = (struct globaldata *) alpha_pal_rdval(); + p = curproc; +#ifdef SMP + p->p_md.md_kernnest++; + critical_exit(s); +#endif cnt.v_trap++; - p = curproc; ucode = 0; user = (framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0; if (user) { @@ -704,11 +714,22 @@ syscall(code, framep) u_quad_t sticks; u_int64_t args[10]; /* XXX */ u_int hidden = 0, nargs; +#ifdef SMP + critical_t s; +#endif /* * Find our per-cpu globals. */ +#ifdef SMP + s = critical_enter(); +#endif globalp = (struct globaldata *) alpha_pal_rdval(); + p = curproc; +#ifdef SMP + p->p_md.md_kernnest++; + critical_exit(s); +#endif mtx_lock(&Giant); framep->tf_regs[FRAME_TRAPARG_A0] = 0; @@ -720,7 +741,6 @@ syscall(code, framep) #endif cnt.v_syscall++; - p = curproc; p->p_md.md_tf = framep; opc = framep->tf_regs[FRAME_PC] - 4; mtx_lock_spin(&sched_lock); diff --git a/sys/alpha/include/proc.h b/sys/alpha/include/proc.h index d003816ab0b..3a83c3942f7 100644 --- a/sys/alpha/include/proc.h +++ b/sys/alpha/include/proc.h @@ -50,6 +50,7 @@ struct mdproc { struct mdbpt md_sstep[2]; /* two single step breakpoints */ u_int64_t md_hae; /* user HAE register value */ void *osf_sigtramp; /* user-level signal trampoline */ + u_int md_kernnest; /* nesting level in the kernel */ }; #define MDP_FPUSED 0x0001 /* Process used the FPU */ diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c index 51046549ce3..03990ea51b3 100644 --- a/sys/powerpc/powerpc/genassym.c +++ b/sys/powerpc/powerpc/genassym.c @@ -84,6 +84,9 @@ ASSYM(P_ADDR, offsetof(struct proc, p_addr)); ASSYM(P_MD_FLAGS, offsetof(struct proc, p_md.md_flags)); ASSYM(P_MD_PCBPADDR, offsetof(struct proc, p_md.md_pcbpaddr)); ASSYM(P_MD_HAE, offsetof(struct proc, p_md.md_hae)); +#ifdef SMP +ASSYM(P_MD_KERNNEST, offsetof(struct proc, p_md.md_kernnest)); +#endif ASSYM(MDP_HAEUSED, MDP_HAEUSED); ASSYM(CHIPSET_WRITE_HAE, offsetof(struct alpha_chipset, write_hae));