Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sparc64/sparc64 sun4v: Add handling of trap 0x06c @...



details:   https://anonhg.NetBSD.org/src/rev/a44f46b149ed
branches:  trunk
changeset: 823309:a44f46b149ed
user:      palle <palle%NetBSD.org@localhost>
date:      Tue Apr 18 20:02:50 2017 +0000

description:
sun4v: Add handling of trap 0x06c @ trap level 1 - based on code from OpenBSD, but slightly adapted to NetBSD. verified using qemu

diffstat:

 sys/arch/sparc64/sparc64/locore.s |  263 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 256 insertions(+), 7 deletions(-)

diffs (truncated from 313 to 300 lines):

diff -r cea1785f2aa7 -r a44f46b149ed sys/arch/sparc64/sparc64/locore.s
--- a/sys/arch/sparc64/sparc64/locore.s Tue Apr 18 19:41:27 2017 +0000
+++ b/sys/arch/sparc64/sparc64/locore.s Tue Apr 18 20:02:50 2017 +0000
@@ -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 @@
        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 @@
        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 @@
 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 @@
        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 @@
         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
+



Home | Main Index | Thread Index | Old Index