summaryrefslogtreecommitdiffstats
path: root/sys/alpha
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-04-24 21:06:53 +0000
committerjhb <jhb@FreeBSD.org>2001-04-24 21:06:53 +0000
commit7f17e1a5d9fcd3c26f189f4b66bfa38bce98f1a2 (patch)
treeab324811176a4122ecd43e5e854ca8ceccd25184 /sys/alpha
parent2d5016b9030b8d30fe7da34abe818822947c208f (diff)
downloadFreeBSD-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.s43
-rw-r--r--sys/alpha/alpha/genassym.c3
-rw-r--r--sys/alpha/alpha/interrupt.c10
-rw-r--r--sys/alpha/alpha/machdep.c3
-rw-r--r--sys/alpha/alpha/trap.c24
-rw-r--r--sys/alpha/include/proc.h1
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 */
OpenPOWER on IntegriCloud