diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S index 58ea5dd8573c..b8678b5557aa 100644 --- a/arch/sparc64/kernel/sun4v_tlb_miss.S +++ b/arch/sparc64/kernel/sun4v_tlb_miss.S @@ -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) \ diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S index 819a6ef9799f..c848c8847cdc 100644 --- a/arch/sparc64/kernel/tsb.S +++ b/arch/sparc64/kernel/tsb.S @@ -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) diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index 1608ba4bf1c1..a9d210e11eb3 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S @@ -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 @@ -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) diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h index f912f52c0c7f..972f913709a3 100644 --- a/include/asm-sparc64/ttable.h +++ b/include/asm-sparc64/ttable.h @@ -180,6 +180,26 @@ #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 *