[SPARC64]: Implement sun4v TSB miss handlers.
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>
This commit is contained in:
@@ -187,6 +187,57 @@ sun4v_dtlb_prot:
|
|||||||
ba,pt %xcc, sparc64_realfault_common
|
ba,pt %xcc, sparc64_realfault_common
|
||||||
mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
|
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 BRANCH_ALWAYS 0x10680000
|
||||||
#define NOP 0x01000000
|
#define NOP 0x01000000
|
||||||
#define SUN4V_DO_PATCH(OLD, NEW) \
|
#define SUN4V_DO_PATCH(OLD, NEW) \
|
||||||
|
@@ -35,8 +35,11 @@ tsb_miss_itlb:
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
/* The sun4v TLB miss handlers jump directly here instead
|
/* The sun4v TLB miss handlers jump directly here instead
|
||||||
* of tsb_miss_{d,i}tlb with the missing virtual address
|
* of tsb_miss_{d,i}tlb with registers setup as follows:
|
||||||
* already loaded into %g4.
|
*
|
||||||
|
* %g4: missing virtual address
|
||||||
|
* %g1: TSB entry address loaded
|
||||||
|
* %g6: TAG TARGET ((vaddr >> 22) | (ctx << 48))
|
||||||
*/
|
*/
|
||||||
tsb_miss_page_table_walk:
|
tsb_miss_page_table_walk:
|
||||||
TRAP_LOAD_PGD_PHYS(%g7, %g5)
|
TRAP_LOAD_PGD_PHYS(%g7, %g5)
|
||||||
|
@@ -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/SUN4V extensions.
|
||||||
* ttable.S: Sparc V9 Trap Table(s) with SpitFire/Cheetah 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>
|
#include <linux/config.h>
|
||||||
@@ -22,7 +21,8 @@ tl0_iax: membar #Sync
|
|||||||
tl0_resv009: BTRAP(0x9)
|
tl0_resv009: BTRAP(0x9)
|
||||||
tl0_iae: membar #Sync
|
tl0_iae: membar #Sync
|
||||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
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
|
tl0_ill: membar #Sync
|
||||||
TRAP_7INSNS(do_illegal_instruction)
|
TRAP_7INSNS(do_illegal_instruction)
|
||||||
tl0_privop: TRAP(do_privop)
|
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_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e)
|
||||||
tl0_resv02f: BTRAP(0x2f)
|
tl0_resv02f: BTRAP(0x2f)
|
||||||
tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception)
|
tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception)
|
||||||
tl0_resv031: BTRAP(0x31)
|
tl0_dtsb_4v: SUN4V_DTSB_MISS
|
||||||
tl0_dae: membar #Sync
|
tl0_dae: membar #Sync
|
||||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
||||||
tl0_resv033: BTRAP(0x33)
|
tl0_resv033: BTRAP(0x33)
|
||||||
@@ -185,7 +185,8 @@ tl1_iax: TRAP_NOSAVE(__spitfire_insn_access_exception_tl1)
|
|||||||
tl1_resv009: BTRAPTL1(0x9)
|
tl1_resv009: BTRAPTL1(0x9)
|
||||||
tl1_iae: membar #Sync
|
tl1_iae: membar #Sync
|
||||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
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_ill: TRAPTL1(do_ill_tl1)
|
||||||
tl1_privop: BTRAPTL1(0x11)
|
tl1_privop: BTRAPTL1(0x11)
|
||||||
tl1_resv012: BTRAPTL1(0x12) BTRAPTL1(0x13) BTRAPTL1(0x14) BTRAPTL1(0x15)
|
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_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c)
|
||||||
tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
|
tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
|
||||||
tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1)
|
tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1)
|
||||||
tl1_resv031: BTRAPTL1(0x31)
|
tl1_dtsb_4v: SUN4V_DTSB_MISS
|
||||||
tl1_dae: membar #Sync
|
tl1_dae: membar #Sync
|
||||||
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
TRAP_NOSAVE_7INSNS(__spitfire_access_error)
|
||||||
tl1_resv033: BTRAPTL1(0x33)
|
tl1_resv033: BTRAPTL1(0x33)
|
||||||
|
@@ -180,6 +180,26 @@
|
|||||||
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
|
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
|
||||||
#endif
|
#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
|
/* Before touching these macros, you owe it to yourself to go and
|
||||||
* see how arch/sparc64/kernel/winfixup.S works... -DaveM
|
* see how arch/sparc64/kernel/winfixup.S works... -DaveM
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user