diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/hppa/hppa/locore.S | 137 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/trap.c | 80 |
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 |