Module Name: src Committed By: palle Date: Tue Apr 18 20:02:50 UTC 2017
Modified Files: src/sys/arch/sparc64/sparc64: locore.s Log Message: sun4v: Add handling of trap 0x06c @ trap level 1 - based on code from OpenBSD, but slightly adapted to NetBSD. verified using qemu To generate a diff of this commit: cvs rdiff -u -r1.409 -r1.410 src/sys/arch/sparc64/sparc64/locore.s Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/sparc64/sparc64/locore.s diff -u src/sys/arch/sparc64/sparc64/locore.s:1.409 src/sys/arch/sparc64/sparc64/locore.s:1.410 --- src/sys/arch/sparc64/sparc64/locore.s:1.409 Sun Feb 19 18:25:45 2017 +++ src/sys/arch/sparc64/sparc64/locore.s Tue Apr 18 20:02:50 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.s,v 1.409 2017/02/19 18:25:45 palle Exp $ */ +/* $NetBSD: locore.s,v 1.410 2017/04/18 20:02:50 palle Exp $ */ /* * Copyright (c) 2006-2010 Matthew R. Green @@ -1102,7 +1102,7 @@ _C_LABEL(trapbase_sun4v): HARDINT4V(14) ! 0x04e = level 14 interrupt HARDINT4V(15) ! 0x04f = level 15 interrupt sun4v_trap_entry 28 ! 0x050-0x06b - VTRAP(T_FDMMU_PROT, sun4v_tl0_dtsb_prot) ! 0x6c + VTRAP(T_FDMMU_PROT, sun4v_tl0_dtsb_prot) ! 0x06c sun4v_trap_entry 15 ! 0x06d-0x07b VTRAP(T_CPU_MONDO, sun4v_cpu_mondo) ! 0x07c = cpu mondo VTRAP(T_DEV_MONDO, sun4v_dev_mondo) ! 0x07d = dev mondo @@ -1149,7 +1149,9 @@ _C_LABEL(trapbase_sun4v): CLEANWIN1 ! 0x24-0x27 = clean window sun4v_trap_entry 9 ! 0x028-0x030 VTRAP(T_DATA_MMU_MISS, sun4v_dtsb_miss) ! 0x031 = data MMU miss - sun4v_trap_entry 78 ! 0x032-0x07f + sun4v_trap_entry 58 ! 0x032-0x06b + VTRAP(T_FDMMU_PROT, sun4v_tl1_dtsb_prot) ! 0x06c + sun4v_trap_entry 19 ! 0x06d-0x07f SPILL64(uspill8_sun4vt1,ASI_AIUS) ! 0x080 spill_0_normal -- save user windows SPILL32(uspill4_sun4vt1,ASI_AIUS) ! 0x084 spill_1_normal SPILLBOTH(uspill8_sun4vt1,uspill4_sun4vt1,ASI_AIUS) ! 0x088 spill_2_normal @@ -2952,8 +2954,7 @@ sun4v_tl0_dtsb_prot: 1: LDPTRA [%g6] ASI_PHYS_CACHED, %g4 ! Fetch TTE brgez,pn %g4, sun4v_datatrap ! Entry invalid? Punt - or %g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g7 - ! Update the modified bit + or %g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g7 ! Update the modified bit # btst SUN4V_TLB_REAL_W|SUN4V_TLB_W, %g4 ! Is it a ref fault? mov 1, %g2 @@ -2965,8 +2966,7 @@ sun4v_tl0_dtsb_prot: casxa [%g6] ASI_PHYS_CACHED, %g4, %g7 ! and write it out cmp %g4, %g7 bne,pn %xcc, 1b - or %g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g4 - ! Update the modified bit + or %g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g4 ! Update the modified bit 2: GET_TSB_DMMU %g2 @@ -3146,6 +3146,253 @@ sun4v_texttrap: nop NOTREACHED +sun4v_tl1_dtsb_prot: + GET_MMFSA %g1 ! MMU Fault status area + add %g1, 0x48, %g3 + LDPTRA [%g3] ASI_PHYS_CACHED, %g3 ! Data fault address + add %g1, 0x50, %g6 + LDPTRA [%g6] ASI_PHYS_CACHED, %g6 ! Data fault context + + GET_CTXBUSY %g4 + sllx %g6, 3, %g6 ! Make it into an offset into ctxbusy + LDPTR [%g4 + %g6], %g4 ! Load up our page table. + + srax %g3, HOLESHIFT, %g5 ! Check for valid address + brz,pt %g5, 0f ! Should be zero or -1 + inc %g5 ! Make -1 -> 0 + brnz,pn %g5, sun4v_tl1_ptbl_miss ! Error! In hole! +0: + srlx %g3, STSHIFT, %g6 + and %g6, STMASK, %g6 ! Index into pm_segs + sll %g6, 3, %g6 + add %g4, %g6, %g4 + LDPTRA [%g4] ASI_PHYS_CACHED, %g4 ! Load page directory pointer + + srlx %g3, PDSHIFT, %g6 + and %g6, PDMASK, %g6 + sll %g6, 3, %g6 + brz,pn %g4, sun4v_tl1_ptbl_miss ! NULL entry? check somewhere else + add %g4, %g6, %g4 + LDPTRA [%g4] ASI_PHYS_CACHED, %g4 ! Load page table pointer + + srlx %g3, PTSHIFT, %g6 ! Convert to ptab offset + and %g6, PTMASK, %g6 + sll %g6, 3, %g6 + brz,pn %g4, sun4v_tl1_ptbl_miss ! NULL entry? check somewhere else + add %g4, %g6, %g6 +1: + LDPTRA [%g6] ASI_PHYS_CACHED, %g4 ! Fetch TTE + brgez,pn %g4, sun4v_tl1_ptbl_miss ! Entry invalid? Punt + or %g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g7 ! Update the modified bit + +# btst SUN4V_TLB_REAL_W|SUN4V_TLB_W, %g4 ! Is it a ref fault? + mov 1, %g2 + sllx %g2, 61, %g2 + or %g2, SUN4V_TLB_W, %g2 + btst %g2, %g4 + bz,pn %xcc, sun4v_tl1_ptbl_miss ! No -- really fault + nop + casxa [%g6] ASI_PHYS_CACHED, %g4, %g7 ! and write it out + cmp %g4, %g7 + bne,pn %xcc, 1b + or %g4, SUN4V_TLB_MODIFY|SUN4V_TLB_ACCESS|SUN4V_TLB_W, %g4 ! Update the modified bit +2: + GET_TSB_DMMU %g2 + + mov %g1, %g7 ! save MMFSA + + /* Construct TSB tag word. */ + add %g1, 0x50, %g6 + LDPTRA [%g6] ASI_PHYS_CACHED, %g6 ! Data fault context + mov %g3, %g1 ! Data fault address + srlx %g1, 22, %g1 ! 63..22 of virt addr + sllx %g6, 48, %g6 ! context_id in 63..48 + or %g1, %g6, %g1 ! construct TTE tag + + srlx %g3, PTSHIFT, %g3 + sethi %hi(_C_LABEL(tsbsize)), %g5 + mov 512, %g6 + ld [%g5 + %lo(_C_LABEL(tsbsize))], %g5 + sllx %g6, %g5, %g5 ! %g5 = 512 << tsbsize = TSBENTS + sub %g5, 1, %g5 ! TSBENTS -> offset + and %g3, %g5, %g3 ! mask out TTE index + sllx %g3, 4, %g3 ! TTE size is 16 bytes + add %g2, %g3, %g2 ! location of TTE in ci_tsb_dmmu + + membar #StoreStore + + STPTR %g4, [%g2 + 8] ! store TTE data + STPTR %g1, [%g2] ! store TTE tag + + mov %o0, %g1 + mov %o1, %g2 + mov %o2, %g3 + + add %g7, 0x48, %o0 + ldxa [%o0] ASI_PHYS_CACHED, %o0 ! Data fault address + add %g7, 0x50, %o1 + ldxa [%o1] ASI_PHYS_CACHED, %o1 ! Data fault context + mov MAP_DTLB, %o2 + ta ST_MMU_UNMAP_ADDR + + mov %g1, %o0 + mov %g2, %o1 + mov %g3, %o2 + + retry + NOTREACHED + +sun4v_tl1_ptbl_miss: + rdpr %tpc, %g1 + + set rft_user_fault_start, %g2 + cmp %g1, %g2 + blu,pt %xcc, 1f + set rft_user_fault_end, %g2 + cmp %g1, %g2 + bgeu,pt %xcc, 1f + nop + + /* Fixup %cwp. */ + rdpr %cwp, %g1 + inc %g1 + wrpr %g1, %cwp + + rdpr %tt, %g1 + wrpr 1, %tl + wrpr %g1, %tt + rdpr %cwp, %g1 + set TSTATE_KERN, %g2 + wrpr %g1, %g2, %tstate + set return_from_trap, %g1 + wrpr %g1, %tpc + add %g1, 4, %g1 + wrpr %g1, %tnpc + wrpr %g0, 1, %gl + + ba,pt %xcc, sun4v_datatrap + wrpr WSTATE_KERN, %wstate + +1: + rdpr %tstate, %g3 + rdpr %tt, %g4 + + rdpr %tl, %g1 + dec %g1 + wrpr %g1, %tl + rdpr %tt, %g2 + inc %g1 + wrpr %g1, %tl + + wrpr %g0, %g3, %tstate + wrpr %g0, %g4, %tt + + andn %g2, 0x00f, %g3 + cmp %g3, 0x080 + be,pn %icc, flush_normals + nop + cmp %g3, 0x0a0 + be,pn %icc, flush_others + nop + cmp %g3, 0x0c0 + be,pn %icc, ufill_trap + nop + + Debugger() + NOTREACHED + +flush_others: + set pcbspill_others, %g1 + wrpr %g1, %tnpc + done + NOTREACHED + +flush_normals: +ufill_trap: + + /* + * Rearrange our trap state such that it appears as if we got + * this trap directly from user mode. Then process it at TL = 1. + * We'll take the spill/fill trap again once we return to user mode. + */ + rdpr %tt, %g1 + rdpr %tstate, %g3 + wrpr %g0, 1, %tl + wrpr %g0, %g1, %tt + rdpr %tstate, %g2 + wrpr %g0, 2, %tl + and %g2, TSTATE_CWP, %g2 + andn %g3, TSTATE_CWP, %g3 + wrpr %g2, %g3, %tstate + set sun4v_datatrap, %g4 + wrpr %g0, %g4, %tnpc + done + +/* + * Spill user windows into the PCB. + */ +pcbspill_normals: + ba,pt %xcc, pcbspill + wrpr 0x80, %tt + +pcbspill_others: + wrpr 0xa0, %tt + +pcbspill: + set CPUINFO_VA, %g6 + ldx [%g6 + CI_CPCB], %g6 + + GET_CTXBUSY %g1 + + ldx [%g1], %g1 ! kernel pmap is ctx 0 + + srlx %g6, STSHIFT, %g7 + and %g7, STMASK, %g7 + sll %g7, 3, %g7 ! byte offset into ctxbusy + add %g7, %g1, %g1 + ldxa [%g1] ASI_PHYS_CACHED, %g1 ! Load pointer to directory + + srlx %g6, PDSHIFT, %g7 ! Do page directory + and %g7, PDMASK, %g7 + sll %g7, 3, %g7 + brz,pn %g1, pcbspill_fail + add %g7, %g1, %g1 + ldxa [%g1] ASI_PHYS_CACHED, %g1 + srlx %g6, PTSHIFT, %g7 ! Convert to ptab offset + and %g7, PTMASK, %g7 + brz %g1, pcbspill_fail + sll %g7, 3, %g7 + add %g1, %g7, %g7 + ldxa [%g7] ASI_PHYS_CACHED, %g7 ! This one is not + brgez %g7, pcbspill_fail + srlx %g7, PGSHIFT, %g7 ! Isolate PA part + sll %g6, 32-PGSHIFT, %g6 ! And offset + sllx %g7, PGSHIFT+8, %g7 ! There are 8 bits to the left of the PA in the TTE + srl %g6, 32-PGSHIFT, %g6 + srax %g7, 8, %g7 + or %g7, %g6, %g6 ! Then combine them to form PA + + wr %g0, ASI_PHYS_CACHED, %asi ! Use ASI_PHYS_CACHED to prevent possible page faults + + lduba [%g6 + PCB_NSAVED] %asi, %g7 + sllx %g7, 7, %g5 + add %g6, %g5, %g5 + SPILL stxa, %g5 + PCB_RW, 8, %asi + saved + + sllx %g7, 3, %g5 + add %g6, %g5, %g5 + + inc %g7 + stba %g7, [%g6 + PCB_NSAVED] %asi + + retry + NOTREACHED + +pcbspill_fail: + Debugger() + NOTREACHED + /* * End of traps for sun4v. */ @@ -4771,7 +5018,9 @@ rft_user: rdpr %cwp, %g4 dec %g4 wrpr %g4, 0, %cwp +rft_user_fault_start: FILL ldxa, %sp+BIAS, 8, %asi +rft_user_fault_end: restored inc %g4 wrpr %g4, 0, %cwp