Commit aa9143b9 authored by David S. Miller's avatar David S. Miller
Browse files

[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: default avatarDavid S. Miller <davem@davemloft.net>
parent 12816ab3
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -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)	\
+5 −2
Original line number Diff line number Diff line
@@ -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)
+8 −7
Original line number Diff line number Diff line
/* $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)
+20 −0
Original line number Diff line number Diff line
@@ -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
 *