[SPARC64]: Implement sun4v TSB miss handlers.
authorDavid S. Miller <davem@sunset.davemloft.net>
Fri, 10 Feb 2006 00:12:22 +0000 (16:12 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 20 Mar 2006 09:12:05 +0000 (01:12 -0800)
When we register a TSB with the hypervisor, so that it or hardware can
handle TLB misses and do the TSB walk for us, the hypervisor traps
down to these trap when it incurs a TSB miss.

Processing is simple, we load the missing virtual address and context,
and do a full page table walk.

Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc64/kernel/sun4v_tlb_miss.S
arch/sparc64/kernel/tsb.S
arch/sparc64/kernel/ttable.S
include/asm-sparc64/ttable.h

index 58ea5dd8573c902d37c84475318d704d07198b4a..b8678b5557aa611cc8b99ce8e8eeb2c840bb07bd 100644 (file)
@@ -187,6 +187,57 @@ sun4v_dtlb_prot:
        ba,pt           %xcc, sparc64_realfault_common
         mov            FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
 
+       /* Called from trap table with &trap_block[smp_processor_id()] in
+        * %g5 and SCRATCHPAD_UTSBREG1 contents in %g1.
+        */
+sun4v_itsb_miss:
+       ldx     [%g5 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_ADDR_OFFSET], %g4
+       ldx     [%g5 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_I_CTX_OFFSET], %g5
+
+       srlx    %g4, 22, %g7
+       sllx    %g5, 48, %g6
+       or      %g6, %g7, %g6
+       brz,pn  %g5, kvmap_itlb_4v
+        nop
+
+       ba,pt   %xcc, sun4v_tsb_miss_common
+        mov    FAULT_CODE_ITLB, %g3
+
+       /* Called from trap table with &trap_block[smp_processor_id()] in
+        * %g5 and SCRATCHPAD_UTSBREG1 contents in %g1.
+        */
+sun4v_dtsb_miss:
+       ldx     [%g5 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_ADDR_OFFSET], %g4
+       ldx     [%g5 + TRAP_PER_CPU_FAULT_INFO + HV_FAULT_D_CTX_OFFSET], %g5
+
+       srlx    %g4, 22, %g7
+       sllx    %g5, 48, %g6
+       or      %g6, %g7, %g6
+       brz,pn  %g5, kvmap_dtlb_4v
+        nop
+
+       mov     FAULT_CODE_DTLB, %g3
+
+       /* Create TSB pointer into %g1.  This is something like:
+        *
+        * index_mask = (512 << (tsb_reg & 0x7UL)) - 1UL;
+        * tsb_base = tsb_reg & ~0x7UL;
+        * tsb_index = ((vaddr >> PAGE_SHIFT) & tsb_mask);
+        * tsb_ptr = tsb_base + (tsb_index * 16);
+        */
+sun4v_tsb_miss_common:
+       and     %g1, 0x7, %g2
+       andn    %g1, 0x7, %g1
+       mov     512, %g7
+       sllx    %g7, %g2, %g7
+       sub     %g7, 1, %g7
+       srlx    %g4, PAGE_SHIFT, %g2
+       and     %g2, %g7, %g2
+       sllx    %g2, 4, %g2
+       ba,pt   %xcc, tsb_miss_page_table_walk
+        add    %g1, %g2, %g1
+
+
 #define BRANCH_ALWAYS  0x10680000
 #define NOP            0x01000000
 #define SUN4V_DO_PATCH(OLD, NEW)       \
index 819a6ef9799fd21c06738b8821d863f493f28b02..c848c8847cdcbbb0a9d60d8dd6f0ba85225aaf08 100644 (file)
@@ -35,8 +35,11 @@ tsb_miss_itlb:
         nop
 
        /* The sun4v TLB miss handlers jump directly here instead
-        * of tsb_miss_{d,i}tlb with the missing virtual address
-        * already loaded into %g4.
+        * of tsb_miss_{d,i}tlb with registers setup as follows:
+        *
+        * %g4: missing virtual address
+        * %g1: TSB entry address loaded
+        * %g6: TAG TARGET ((vaddr >> 22) | (ctx << 48))
         */
 tsb_miss_page_table_walk:
        TRAP_LOAD_PGD_PHYS(%g7, %g5)
index 1608ba4bf1c14688cac6afe664d06faeb7f3b886..a9d210e11eb3f8210e85ab510f6ed78e43aaf452 100644 (file)
@@ -1,7 +1,6 @@
-/* $Id: ttable.S,v 1.38 2002/02/09 19:49:30 davem Exp $
- * ttable.S: Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
+/* ttable.S: Sparc V9 Trap Table(s) with SpitFire/Cheetah/SUN4V extensions.
  *
- * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2001, 2006 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/config.h>
@@ -22,7 +21,8 @@ tl0_iax:      membar #Sync
 tl0_resv009:   BTRAP(0x9)
 tl0_iae:       membar #Sync
                TRAP_NOSAVE_7INSNS(__spitfire_access_error)
-tl0_resv00b:   BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
+tl0_itsb_4v:   SUN4V_ITSB_MISS
+tl0_resv00c:   BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
 tl0_ill:       membar #Sync
                TRAP_7INSNS(do_illegal_instruction)
 tl0_privop:    TRAP(do_privop)
@@ -38,7 +38,7 @@ tl0_div0:     TRAP(do_div0)
 tl0_resv029:   BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e)
 tl0_resv02f:   BTRAP(0x2f)
 tl0_dax:       TRAP_NOSAVE(__spitfire_data_access_exception)
-tl0_resv031:   BTRAP(0x31)
+tl0_dtsb_4v:   SUN4V_DTSB_MISS
 tl0_dae:       membar #Sync
                TRAP_NOSAVE_7INSNS(__spitfire_access_error)
 tl0_resv033:   BTRAP(0x33)
@@ -185,7 +185,8 @@ tl1_iax:    TRAP_NOSAVE(__spitfire_insn_access_exception_tl1)
 tl1_resv009:   BTRAPTL1(0x9)
 tl1_iae:       membar #Sync
                TRAP_NOSAVE_7INSNS(__spitfire_access_error)
-tl1_resv00b:   BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf)
+tl1_itsb_4v:   SUN4V_ITSB_MISS
+tl1_resv00c:   BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf)
 tl1_ill:       TRAPTL1(do_ill_tl1)
 tl1_privop:    BTRAPTL1(0x11)
 tl1_resv012:   BTRAPTL1(0x12) BTRAPTL1(0x13) BTRAPTL1(0x14) BTRAPTL1(0x15)
@@ -201,7 +202,7 @@ tl1_div0:   TRAPTL1(do_div0_tl1)
 tl1_resv029:   BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c)
 tl1_resv02d:   BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
 tl1_dax:       TRAP_NOSAVE(__spitfire_data_access_exception_tl1)
-tl1_resv031:   BTRAPTL1(0x31)
+tl1_dtsb_4v:   SUN4V_DTSB_MISS
 tl1_dae:       membar #Sync
                TRAP_NOSAVE_7INSNS(__spitfire_access_error)
 tl1_resv033:   BTRAPTL1(0x33)
index f912f52c0c7ffde0b870ab83ae1db4d62b34b5e7..972f913709a33c1a4c7e1f6213876a46d223cd88 100644 (file)
 #define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
 #endif
 
+#define SUN4V_ITSB_MISS                                \
+       mov     SCRATCHPAD_CPUID, %g1;          \
+       ldxa    [%g1] ASI_SCRATCHPAD, %g2;      \
+       ldxa    [%g1 + %g1] ASI_SCRATCHPAD, %g1;\
+       sethi   %hi(trap_block), %g5;           \
+       sllx    %g2, TRAP_BLOCK_SZ_SHIFT, %g2;  \
+       or      %g5, %lo(trap_block), %g5;      \
+       ba,pt   %xcc, sun4v_itsb_miss;          \
+        add    %g5, %g2, %g5;
+
+#define SUN4V_DTSB_MISS                                \
+       mov     SCRATCHPAD_CPUID, %g1;          \
+       ldxa    [%g1] ASI_SCRATCHPAD, %g2;      \
+       ldxa    [%g1 + %g1] ASI_SCRATCHPAD, %g1;\
+       sethi   %hi(trap_block), %g5;           \
+       sllx    %g2, TRAP_BLOCK_SZ_SHIFT, %g2;  \
+       or      %g5, %lo(trap_block), %g5;      \
+       ba,pt   %xcc, sun4v_dtsb_miss;          \
+        add    %g5, %g2, %g5;
+
 /* Before touching these macros, you owe it to yourself to go and
  * see how arch/sparc64/kernel/winfixup.S works... -DaveM
  *