summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/hppa/hppa/locore.S137
-rw-r--r--sys/arch/hppa/hppa/trap.c80
2 files changed, 159 insertions, 58 deletions
diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S
index 5d4c2cd6567..b9805990b02 100644
--- a/sys/arch/hppa/hppa/locore.S
+++ b/sys/arch/hppa/hppa/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.143 2004/12/24 22:50:29 miod Exp $ */
+/* $OpenBSD: locore.S,v 1.144 2005/01/17 19:01:00 mickey Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
@@ -1197,18 +1197,18 @@ EXIT(TLABEL(emu))
#endif
#if defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU)
-#define TLB_PULL(bits) ! \
+#define TLB_PULL(bits,lbl) ! \
/* space:pgaddr -- r8:r9 */ ! \
mfctl vtop, r16 ! \
ldwax,s r8(r16), r17 /* space -> page directory */ ! \
extru r9, 9, 10, r25 ! \
- combt,=,n r0, r17, TLABEL(all) ! \
+ combt,=,n r0, r17, lbl ! \
ldwax,s r25(r17), r24 /* page -> page table */ ! \
extru r9, 19, 10, r16 ! \
- combt,=,n r0, r24, TLABEL(all) ! \
+ combt,=,n r0, r24, lbl ! \
ldwax,s r16(r24), r17 /* va -> pa:prot */ ! \
sh2addl r16, r24, r25 ! \
- combt,=,n r0, r17, TLABEL(all) ! \
+ combt,=,n r0, r17, lbl ! \
copy r17, r16 ! \
depi (bits), 21+bits, 1+bits, r17 ! \
sub,= r16, r17, r0 /* do not store if unchanged */ ! \
@@ -1223,7 +1223,7 @@ EXIT(TLABEL(emu))
$tlbd_s
$tlbd_t
TLB_STATS_PRE(tlbd)
- TLB_PULL(1)
+ TLB_PULL(1, TLABEL(all))
mfsp sr1, r16
mtsp r8, sr1
idtlba r17,(sr1, r9)
@@ -1234,11 +1234,9 @@ $tlbd_t
nop
$itlb_s
-$itlbna_s
$itlb_t
-$itlbna_t
TLB_STATS_PRE(itlb)
- TLB_PULL(0)
+ TLB_PULL(0, TLABEL(all))
extru,= r25, 5, 1, r0 /* gate needs a kernel pid */
depi 0, 30, 15, r25
mfsp sr1, r16
@@ -1251,11 +1249,46 @@ $itlbna_t
nop
$dtlb_s
-$dtlbna_s
$dtlb_t
+ TLB_STATS_PRE(dtlb)
+ TLB_PULL(0, TLABEL(all))
+ mfsp sr1, r16
+ mtsp r8, sr1
+ idtlba r17,(sr1, r9)
+ idtlbp r25,(sr1, r9)
+ mtsp r16, sr1
+ TLB_STATS_AFT(dtlb)
+ rfir
+ nop
+
+$itlbna_s
+$dtlbna_s
+$itlbna_t
$dtlbna_t
TLB_STATS_PRE(dtlb)
- TLB_PULL(0)
+ TLB_PULL(0, $dtlbna_t_fake)
+ mfsp sr1, r16
+ mtsp r8, sr1
+ idtlba r17,(sr1, r9)
+ idtlbp r25,(sr1, r9)
+ mtsp r16, sr1
+ TLB_STATS_AFT(dtlb)
+ rfir
+ nop
+$dtlbna_s_fake
+$dtlbna_t_fake
+ /* parse prober/w insns, have to decent to trap() to set regs proper */
+ mfctl iir, r16
+ extru r16, 6, 6, r24
+ comib,=,n 1, r24, TLABEL(all)
+ extru r16, 24, 6, r24
+ subi,<> 0x23, r24, r0
+ b TLABEL(all)
+ /* otherwise generate a flush-only tlb entry */
+ copy r0, r17
+ zdep r8, 30, 15, r25
+ depi -13, 11, 7, r25
+ ldo 2(r25), r25 /* 3? */
mfsp sr1, r16
mtsp r8, sr1
idtlba r17,(sr1, r9)
@@ -1264,6 +1297,7 @@ $dtlbna_t
TLB_STATS_AFT(dtlb)
rfir
nop
+
#endif /* defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) */
#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
@@ -1278,18 +1312,18 @@ $dtlbna_t
* change pte to reduce number of shifts
* reorder to reduce stalls
*/
-#define TLB_PULL_L(bits) ! \
+#define TLB_PULL_L(bits,lbl) ! \
/* space:pgaddr -- r8:r9 */ ! \
mfctl vtop, r16 ! \
ldwx,s r8(r16), r17 /* space -> page directory */ ! \
extru r9, 9, 10, r25 ! \
- combt,=,n r0, r17, TLABEL(all) ! \
+ combt,=,n r0, r17, lbl ! \
ldwx,s r25(r17), r24 /* page -> page table */ ! \
extru r9, 19, 10, r16 ! \
- combt,=,n r0, r24, TLABEL(all) ! \
+ combt,=,n r0, r24, lbl ! \
ldwx,s r16(r24), r17 /* va -> pa:prot */ ! \
sh2addl r16, r24, r25 ! \
- combt,=,n r0, r17, TLABEL(all) ! \
+ combt,=,n r0, r17, lbl ! \
copy r17, r16 ! \
depi (bits), 21+bits, 1+bits, r17 ! \
sub,= r16, r17, r0 /* do not store if unchanged */ ! \
@@ -1304,7 +1338,7 @@ $dtlbna_t
.align 32
$tlbd_l
TLB_STATS_PRE(tlbd)
- TLB_PULL_L(1)
+ TLB_PULL_L(1, TLABEL(all))
IDTLBAF(17)
IDTLBPF(25)
#ifdef USE_HPT
@@ -1325,9 +1359,8 @@ $tlbd_l
* unreliable for the itlb miss handler
*/
$itlb_l
-$itlbna_l
TLB_STATS_PRE(itlb)
- TLB_PULL_L(0)
+ TLB_PULL_L(0, TLABEL(all))
extru,= r25, 5, 1, r0 /* gate needs a kernel pid */
depi 0, 30, 15, r25
IITLBAF(17)
@@ -1335,18 +1368,38 @@ $itlbna_l
TLB_STATS_AFT(itlb)
rfir
nop
+
+$itlbna_l
$dtlbna_l
TLB_STATS_PRE(dtlb)
- TLB_PULL_L(0)
+ TLB_PULL_L(0, $dtlbna_l_fake)
+ IDTLBAF(17)
+ IDTLBPF(25)
+ TLB_STATS_AFT(dtlb)
+ rfir
+ nop
+$dtlbna_l_fake
+ /* parse prober/w insns, have to decent to trap() to set regs proper */
+ mfctl iir, r16
+ extru r16, 6, 6, r24
+ comib,=,n 1, r24, TLABEL(all)
+ extru r16, 24, 6, r24
+ subi,<> 0x23, r24, r0
+ b TLABEL(all)
+ /* otherwise generate a flush-only tlb entry */
+ copy r0, r17
+ zdep r8, 30, 15, r25
+ depi -13, 11, 7, r25
+ ldo 2(r25), r25 /* 3? */
IDTLBAF(17)
IDTLBPF(25)
- /* figure out later if it's worth caching mappings here as well */
TLB_STATS_AFT(dtlb)
rfir
nop
+
$dtlb_l
TLB_STATS_PRE(dtlb)
- TLB_PULL_L(0)
+ TLB_PULL_L(0, TLABEL(all))
IDTLBAF(17)
IDTLBPF(25)
#ifdef USE_HPT
@@ -1417,7 +1470,7 @@ $dtlb_done_l
$tlbd_u
TLB_STATS_PRE(tlbd)
- TLB_PULL_L(1)
+ TLB_PULL_L(1, TLABEL(all))
TLB_PCX2PCXU
idtlbt r17, r25
TLB_STATS_AFT(tlbd)
@@ -1425,9 +1478,8 @@ $tlbd_u
nop
$itlb_u
-$itlbna_u
TLB_STATS_PRE(itlb)
- TLB_PULL_L(0)
+ TLB_PULL_L(0, TLABEL(all))
extru,= r25, 5, 1, r0 /* gate needs a kernel pid */
depi 0, 30, 15, r25
TLB_PCX2PCXU
@@ -1436,10 +1488,36 @@ $itlbna_u
rfir
nop
+$itlbna_u
$dtlbna_u
+ TLB_STATS_PRE(dtlb)
+ TLB_PULL_L(0, $dtlbna_u_fake)
+ TLB_PCX2PCXU
+ idtlbt r17, r25
+ TLB_STATS_AFT(dtlb)
+ rfir
+ nop
+$dtlbna_u_fake
+ /* parse prober/w insns, have to decent to trap() to set regs proper */
+ mfctl iir, r16
+ extru r16, 6, 6, r24
+ comib,=,n 1, r24, TLABEL(all)
+ extru r16, 24, 6, r24
+ subi,<> 0x23, r24, r0
+ b TLABEL(all)
+ /* otherwise generate a flush-only tlb entry */
+ copy r0, r17
+ zdep r8, 30, 15, r25
+ depi -13, 11, 7, r25
+ ldo 2(r25), r25 /* 3? */
+ idtlbt r17, r25
+ TLB_STATS_AFT(dtlb)
+ rfir
+ nop
+
$dtlb_u
TLB_STATS_PRE(dtlb)
- TLB_PULL_L(0)
+ TLB_PULL_L(0, TLABEL(all))
TLB_PCX2PCXU
idtlbt r17, r25
TLB_STATS_AFT(dtlb)
@@ -1719,18 +1797,19 @@ $trapnowvirt
/* see if curproc have changed */
ldw -HPPA_FRAME_SIZE-TRAPFRAME_SIZEOF+TF_FLAGS(sp), arg0
- bb,>=,n arg0, TFF_LAST_POS, $syscall_return
ldo -HPPA_FRAME_SIZE-TRAPFRAME_SIZEOF(sp), t3
+ extru,<> arg0, TFF_LAST_POS, 1, r0
+ b $syscall_return
/* see if curproc have really changed */
ldil L%curproc, t1
ldw R%curproc(t1), t2
- comb,=,n r0, t2, $syscall_return
- ldo -HPPA_FRAME_SIZE-TRAPFRAME_SIZEOF(sp), t3
+ sub,<> r0, t2, r0
+ ldw P_MD_REGS(t2), t3
/* means curproc have actually changed */
b $syscall_return
- ldw P_MD_REGS(t2), t3
+ nop
.export $trap$all$end, entry
$trap$all$end
diff --git a/sys/arch/hppa/hppa/trap.c b/sys/arch/hppa/hppa/trap.c
index 022bcc0f97e..b91b012d0d5 100644
--- a/sys/arch/hppa/hppa/trap.c
+++ b/sys/arch/hppa/hppa/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.82 2004/12/06 20:12:24 miod Exp $ */
+/* $OpenBSD: trap.c,v 1.83 2005/01/17 19:01:00 mickey Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
@@ -191,7 +191,6 @@ trap(type, frame)
} else {
va = frame->tf_ior;
space = frame->tf_isr;
- /* what is the vftype for the T_ITLBMISSNA ??? XXX */
if (va == frame->tf_iioq_head)
vftype = UVM_PROT_EXEC;
else if (inst_store(opcode))
@@ -362,6 +361,46 @@ trap(type, frame)
trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
break;
+ case T_ITLBMISSNA:
+ case T_ITLBMISSNA | T_USER:
+ case T_DTLBMISSNA:
+ case T_DTLBMISSNA | T_USER:
+ if (space == HPPA_SID_KERNEL)
+ map = kernel_map;
+ else {
+ vm = p->p_vmspace;
+ map = &vm->vm_map;
+ }
+
+ /* dig probe[rw]i? insns */
+ if ((opcode & 0xfc001f80) == 0x04001180) {
+ int pl;
+
+ if (opcode & 0x2000)
+ pl = (opcode >> 16) & 3;
+ else
+ pl = frame_regmap(frame,
+ (opcode >> 16) & 0x1f) & 3;
+
+ if ((type & T_USER && space == HPPA_SID_KERNEL) ||
+ (frame->tf_iioq_head & 3) != pl ||
+ (type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
+ uvm_fault(map, hppa_trunc_page(va), fault,
+ opcode & 0x40? UVM_PROT_WRITE : UVM_PROT_READ)) {
+ frame_regmap(frame, opcode & 0x1f) = 0;
+ frame->tf_ipsw |= PSL_N;
+ }
+ } else if (type & T_USER) {
+ sv.sival_int = va;
+ trapsignal(p, SIGILL, type & ~T_USER, ILL_ILLTRP, sv);
+ } else
+ panic("trap: %s @ 0x%x:0x%x for 0x%x:0x%x irr 0x%08x\n",
+ tts, frame->tf_iisq_head, frame->tf_iioq_head,
+ space, va, opcode);
+ break;
+
+ case T_TLB_DIRTY:
+ case T_TLB_DIRTY | T_USER:
case T_DATACC:
case T_DATACC | T_USER:
fault = VM_FAULT_PROTECT;
@@ -369,24 +408,6 @@ trap(type, frame)
case T_ITLBMISS | T_USER:
case T_DTLBMISS:
case T_DTLBMISS | T_USER:
- case T_ITLBMISSNA:
- case T_ITLBMISSNA | T_USER:
- case T_DTLBMISSNA:
- case T_DTLBMISSNA | T_USER:
- case T_TLB_DIRTY:
- case T_TLB_DIRTY | T_USER:
- /*
- * user faults out of user addr space are always a fail,
- * this happens on va >= VM_MAXUSER_ADDRESS, where
- * space id will be zero and therefore cause
- * a misbehave lower in the code.
- */
- if (type & T_USER && va >= VM_MAXUSER_ADDRESS) {
- sv.sival_int = va;
- trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
- break;
- }
-
/*
* it could be a kernel map for exec_map faults
*/
@@ -397,7 +418,16 @@ trap(type, frame)
map = &vm->vm_map;
}
- if (type & T_USER && map->pmap->pm_space != space) {
+ /*
+ * user faults out of user addr space are always a fail,
+ * this happens on va >= VM_MAXUSER_ADDRESS, where
+ * space id will be zero and therefore cause
+ * a misbehave lower in the code.
+ *
+ * also check that faulted space id matches the curproc.
+ */
+ if ((type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
+ (type & T_USER && map->pmap->pm_space != space)) {
sv.sival_int = va;
trapsignal(p, SIGSEGV, vftype, SEGV_MAPERR, sv);
break;
@@ -405,14 +435,6 @@ trap(type, frame)
ret = uvm_fault(map, hppa_trunc_page(va), fault, vftype);
- /* dig probe insn */
- if (ret && trapnum == T_DTLBMISSNA &&
- (opcode & 0xfc001f80) == 0x04001180) {
- frame_regmap(frame, opcode & 0x1f) = 0;
- frame->tf_ipsw |= PSL_N;
- break;
- }
-
/*
* If this was a stack access we keep track of the maximum
* accessed stack size. Also, if uvm_fault gets a protection