summaryrefslogtreecommitdiff
path: root/sys/arch/hppa
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2011-11-08 14:02:31 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2011-11-08 14:02:31 +0000
commit7839418944cfb4535cad2499d94f284fc66ade3c (patch)
tree2e737f408958d1ebb024e1aedeaba482bf81ff46 /sys/arch/hppa
parent392103b04974436c258da39c8e09121fe2547090 (diff)
On PCXS processors, reading %cr26 and %cr27 from userland causes a
privileged register trap. Cope with this in the trap handler to let userland use these registers; this will be necessary in the not-so-distant future.
Diffstat (limited to 'sys/arch/hppa')
-rw-r--r--sys/arch/hppa/hppa/trap.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/sys/arch/hppa/hppa/trap.c b/sys/arch/hppa/hppa/trap.c
index f9c2271f206..c75f31bf7cc 100644
--- a/sys/arch/hppa/hppa/trap.c
+++ b/sys/arch/hppa/hppa/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.118 2011/07/11 15:40:47 guenther Exp $ */
+/* $OpenBSD: trap.c,v 1.119 2011/11/08 14:02:30 miod Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
@@ -283,7 +283,7 @@ trap(int type, struct trapframe *frame)
#endif
/* pass to user debugger */
KERNEL_LOCK();
- trapsignal(p, SIGTRAP, type &~ T_USER, code, sv);
+ trapsignal(p, SIGTRAP, type & ~T_USER, code, sv);
KERNEL_UNLOCK();
}
break;
@@ -294,7 +294,7 @@ trap(int type, struct trapframe *frame)
/* pass to user debugger */
KERNEL_LOCK();
- trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_TRACE, sv);
+ trapsignal(p, SIGTRAP, type & ~T_USER, TRAP_TRACE, sv);
KERNEL_UNLOCK();
break;
#endif
@@ -336,7 +336,7 @@ trap(int type, struct trapframe *frame)
sv.sival_int = va;
KERNEL_LOCK();
- trapsignal(p, SIGFPE, type &~ T_USER, flt, sv);
+ trapsignal(p, SIGFPE, type & ~T_USER, flt, sv);
KERNEL_UNLOCK();
}
break;
@@ -348,36 +348,55 @@ trap(int type, struct trapframe *frame)
case T_EMULATION | T_USER:
sv.sival_int = va;
KERNEL_LOCK();
- trapsignal(p, SIGILL, type &~ T_USER, ILL_COPROC, sv);
+ trapsignal(p, SIGILL, type & ~T_USER, ILL_COPROC, sv);
KERNEL_UNLOCK();
break;
case T_OVERFLOW | T_USER:
sv.sival_int = va;
KERNEL_LOCK();
- trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv);
+ trapsignal(p, SIGFPE, type & ~T_USER, FPE_INTOVF, sv);
KERNEL_UNLOCK();
break;
case T_CONDITION | T_USER:
sv.sival_int = va;
KERNEL_LOCK();
- trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTDIV, sv);
+ trapsignal(p, SIGFPE, type & ~T_USER, FPE_INTDIV, sv);
KERNEL_UNLOCK();
break;
case T_PRIV_OP | T_USER:
sv.sival_int = va;
KERNEL_LOCK();
- trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVOPC, sv);
+ trapsignal(p, SIGILL, type & ~T_USER, ILL_PRVOPC, sv);
KERNEL_UNLOCK();
break;
case T_PRIV_REG | T_USER:
- sv.sival_int = va;
- KERNEL_LOCK();
- trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVREG, sv);
- KERNEL_UNLOCK();
+ /*
+ * On PCXS processors, attempting to read control registers
+ * cr26 and cr27 from userland causes a ``privileged register''
+ * trap. Later processors do not restrict read accesses to
+ * these registers.
+ */
+ if (cpu_type == hpcxs &&
+ (opcode & (0xfc1fffe0 | (0x1e << 21))) ==
+ (0x000008a0 | (0x1a << 21))) { /* mfctl %cr{26,27}, %r# */
+ register_t cr;
+
+ if (((opcode >> 21) & 0x1f) == 27)
+ mfctl(CR_TR3, cr); /* cr27 */
+ else
+ mfctl(CR_TR2, cr); /* cr26 */
+ frame_regmap(frame, opcode & 0x1f) = cr;
+ frame->tf_ipsw |= PSL_N;
+ } else {
+ sv.sival_int = va;
+ KERNEL_LOCK();
+ trapsignal(p, SIGILL, type & ~T_USER, ILL_PRVREG, sv);
+ KERNEL_UNLOCK();
+ }
break;
/* these should never got here */
@@ -569,7 +588,7 @@ datalign_user:
if (type & T_USER) {
sv.sival_int = va;
KERNEL_LOCK();
- trapsignal(p, SIGILL, type &~ T_USER, ILL_ILLOPC, sv);
+ trapsignal(p, SIGILL, type & ~T_USER, ILL_ILLOPC, sv);
KERNEL_UNLOCK();
break;
}