diff options
author | jhb <jhb@FreeBSD.org> | 2001-04-24 21:06:53 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-04-24 21:06:53 +0000 |
commit | 7f17e1a5d9fcd3c26f189f4b66bfa38bce98f1a2 (patch) | |
tree | ab324811176a4122ecd43e5e854ca8ceccd25184 /sys/alpha | |
parent | 2d5016b9030b8d30fe7da34abe818822947c208f (diff) | |
download | FreeBSD-src-7f17e1a5d9fcd3c26f189f4b66bfa38bce98f1a2.zip FreeBSD-src-7f17e1a5d9fcd3c26f189f4b66bfa38bce98f1a2.tar.gz |
Add a new field 'md_kernnest' to the alpha machine dependent process
structure. This field keeps track of how many levels deep we are nested
into the kernel. The nesting level is bumped at the start of a trap,
interrupt, syscall, or exception and is decremented on return. This is
used to detect the case when the kernel is returning back to a kernel
context in exception_return(). If we are returning to the kernel we need
to update the globaldata pointer register saved in the stack frame in case
we have switched CPU's between taking the initial interrupt that saved the
frame and returning. If we don't do this fixup it is possible for a CPU to
use the wrong per-cpu data. On UP systems this is not a problem, so the
code is conditional on SMP.
A count was used instead of simply checking the process status register in
the frame during exception_return() since there are critical sections at
the very start and end of a trap, exception, or interrupt from userland in
which we could trash the t7 register being used in userland. The counter
is incremented after adn before these critical sections respectively so
that we will not overwrite the saved t7 register if we are interrupted
during one of these critical sections.
Diffstat (limited to 'sys/alpha')
-rw-r--r-- | sys/alpha/alpha/exception.s | 43 | ||||
-rw-r--r-- | sys/alpha/alpha/genassym.c | 3 | ||||
-rw-r--r-- | sys/alpha/alpha/interrupt.c | 10 | ||||
-rw-r--r-- | sys/alpha/alpha/machdep.c | 3 | ||||
-rw-r--r-- | sys/alpha/alpha/trap.c | 24 | ||||
-rw-r--r-- | sys/alpha/include/proc.h | 1 |
6 files changed, 69 insertions, 15 deletions
diff --git a/sys/alpha/alpha/exception.s b/sys/alpha/alpha/exception.s index bc8ee57..b3bf1dc 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 5104654..03990ea 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 c44eccf..346b21c 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 7803621..f623669 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 1b08a7d..228c50b 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 d003816..3a83c39 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 */ |