[RFC PATCH 04/14] sparc64: load shared id into context register 1

From: Mike Kravetz
Date: Fri Dec 16 2016 - 13:39:48 EST


In current code, only context ID register 0 is set and used by the MMU.
On sun4v platforms that support MMU shared context, there is an additional
context ID register: specifically context register 1. When searching
the TLB, the MMU will find a match if the virtual address matches and
the ID contained in context register 0 -OR- context register 1 matches.

Load the shared context ID into context ID register 1. Care must be
taken to load register 1 after register 0, as loading register 0
overwrites both register 0 and 1. Modify code loading register 0 to
also load register one if applicable.

Signed-off-by: Mike Kravetz <mike.kravetz@xxxxxxxxxx>
---
arch/sparc/include/asm/mmu_context_64.h | 37 +++++++++++++++++--
arch/sparc/include/asm/spitfire.h | 2 ++
arch/sparc/kernel/fpu_traps.S | 63 +++++++++++++++++++++++++++++++++
arch/sparc/kernel/rtrap_64.S | 20 +++++++++++
arch/sparc/kernel/trampoline_64.S | 20 +++++++++++
5 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h
index acaea6d..84268df 100644
--- a/arch/sparc/include/asm/mmu_context_64.h
+++ b/arch/sparc/include/asm/mmu_context_64.h
@@ -61,8 +61,11 @@ void smp_tsb_sync(struct mm_struct *mm);
#define smp_tsb_sync(__mm) do { } while (0)
#endif

-/* Set MMU context in the actual hardware. */
-#define load_secondary_context(__mm) \
+/*
+ * Set MMU context in the actual hardware. Secondary context register
+ * zero is loaded with task specific context.
+ */
+#define load_secondary_context_0(__mm) \
__asm__ __volatile__( \
"\n661: stxa %0, [%1] %2\n" \
" .section .sun4v_1insn_patch, \"ax\"\n" \
@@ -74,6 +77,36 @@ void smp_tsb_sync(struct mm_struct *mm);
: "r" (CTX_HWBITS((__mm)->context)), \
"r" (SECONDARY_CONTEXT), "i" (ASI_DMMU), "i" (ASI_MMU))

+/*
+ * Secondary context register one is loaded with shared context if
+ * it exists for the task.
+ */
+#define load_secondary_context_1(__mm) \
+ __asm__ __volatile__( \
+ "\n661: stxa %0, [%1] %2\n" \
+ " .section .sun4v_1insn_patch, \"ax\"\n" \
+ " .word 661b\n" \
+ " stxa %0, [%1] %3\n" \
+ " .previous\n" \
+ " flush %%g6\n" \
+ : /* No outputs */ \
+ : "r" (SHARED_CTX_HWBITS((__mm)->context)), \
+ "r" (SECONDARY_CONTEXT_R1), "i" (ASI_DMMU), "i" (ASI_MMU))
+
+#if defined(CONFIG_SHARED_MMU_CTX)
+#define load_secondary_context(__mm) \
+ do { \
+ load_secondary_context_0(__mm); \
+ if ((__mm)->context.shared_ctx) \
+ load_secondary_context_1(__mm); \
+ } while (0)
+#else
+#define load_secondary_context(__mm) \
+ do { \
+ load_secondary_context_0(__mm); \
+ } while (0)
+#endif
+
void __flush_tlb_mm(unsigned long, unsigned long);

/* Switch the current MM context. */
diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h
index 1d8321c..1fa4594 100644
--- a/arch/sparc/include/asm/spitfire.h
+++ b/arch/sparc/include/asm/spitfire.h
@@ -33,6 +33,8 @@
#define DMMU_SFAR 0x0000000000000020
#define VIRT_WATCHPOINT 0x0000000000000038
#define PHYS_WATCHPOINT 0x0000000000000040
+#define PRIMARY_CONTEXT_R1 0x0000000000000108
+#define SECONDARY_CONTEXT_R1 0x0000000000000110

#define SPITFIRE_HIGHEST_LOCKED_TLBENT (64 - 1)
#define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1)
diff --git a/arch/sparc/kernel/fpu_traps.S b/arch/sparc/kernel/fpu_traps.S
index 336d275..f85a034 100644
--- a/arch/sparc/kernel/fpu_traps.S
+++ b/arch/sparc/kernel/fpu_traps.S
@@ -73,6 +73,16 @@ do_fpdis:
ldxa [%g3] ASI_MMU, %g5
.previous

+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g3
+ ldxa [%g3] ASI_MMU, %g4
+ .previous
+ /* Unnecessary on sun4u and pre-Niagara 2 sun4v */
+ mov SECONDARY_CONTEXT, %g3
+
sethi %hi(sparc64_kern_sec_context), %g2
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2

@@ -114,6 +124,16 @@ do_fpdis:
ldxa [%g3] ASI_MMU, %g5
.previous

+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g3
+ ldxa [%g3] ASI_MMU, %g4
+ .previous
+ /* Unnecessary on sun4u and pre-Niagara 2 sun4v */
+ mov SECONDARY_CONTEXT, %g3
+
add %g6, TI_FPREGS, %g1
sethi %hi(sparc64_kern_sec_context), %g2
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
@@ -155,6 +175,16 @@ do_fpdis:
ldxa [%g3] ASI_MMU, %g5
.previous

+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g3
+ ldxa [%g3] ASI_MMU, %g4
+ .previous
+ /* Unnecessary on sun4u and pre-Niagara 2 sun4v */
+ mov SECONDARY_CONTEXT, %g3
+
sethi %hi(sparc64_kern_sec_context), %g2
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2

@@ -181,11 +211,24 @@ fpdis_exit:
stxa %g5, [%g3] ASI_MMU
.previous

+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g3
+ stxa %g4, [%g3] ASI_MMU
+ .previous
+
membar #Sync
fpdis_exit2:
wr %g7, 0, %gsr
ldx [%g6 + TI_XFSR], %fsr
rdpr %tstate, %g3
+661: nop
+ .section .sun4v_1insn_patch, "ax"
+ .word 661b
+ sethi %hi(TSTATE_PEF), %g4
+ .previous
or %g3, %g4, %g3 ! anal...
wrpr %g3, %tstate
wr %g0, FPRS_FEF, %fprs ! clean DU/DL bits
@@ -347,6 +390,16 @@ do_fptrap_after_fsr:
ldxa [%g3] ASI_MMU, %g5
.previous

+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g3
+ ldxa [%g3] ASI_MMU, %g4
+ .previous
+ /* Unnecessary on sun4u and pre-Niagara 2 sun4v */
+ mov SECONDARY_CONTEXT, %g3
+
sethi %hi(sparc64_kern_sec_context), %g2
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2

@@ -377,7 +430,17 @@ do_fptrap_after_fsr:
stxa %g5, [%g1] ASI_MMU
.previous

+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g1
+ stxa %g4, [%g1] ASI_MMU
+ .previous
+
membar #Sync
+ /* Unnecessary on sun4u and pre-Niagara 2 sun4v */
+ mov SECONDARY_CONTEXT, %g1
ba,pt %xcc, etrap
wr %g0, 0, %fprs
.size do_fptrap,.-do_fptrap
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 216948c..d409d84 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -202,6 +202,7 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
brnz,pn %l3, kern_rtt
mov PRIMARY_CONTEXT, %l7

+ /* Get value from SECONDARY_CONTEXT register */
661: ldxa [%l7 + %l7] ASI_DMMU, %l0
.section .sun4v_1insn_patch, "ax"
.word 661b
@@ -212,12 +213,31 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
ldx [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1
or %l0, %l1, %l0

+ /* and, put into PRIMARY_CONTEXT register */
661: stxa %l0, [%l7] ASI_DMMU
.section .sun4v_1insn_patch, "ax"
.word 661b
stxa %l0, [%l7] ASI_MMU
.previous

+ /* Get value from SECONDARY_CONTEXT_R1 register */
+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %l7
+ ldxa [%l7] ASI_MMU, %l0
+ .previous
+
+ /* and, put into PRIMARY_CONTEXT_R1 register */
+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov PRIMARY_CONTEXT_R1, %l7
+ stxa %l0, [%l7] ASI_MMU
+ .previous
+
sethi %hi(KERNBASE), %l7
flush %l7
rdpr %wstate, %l1
diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S
index 88ede1d..7c4ab3b 100644
--- a/arch/sparc/kernel/trampoline_64.S
+++ b/arch/sparc/kernel/trampoline_64.S
@@ -260,6 +260,16 @@ after_lock_tlb:
stxa %g0, [%g7] ASI_MMU
.previous

+ /* Save SECONDARY_CONTEXT_R1, membar should be part of patch */
+ membar #Sync
+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g7
+ ldxa [%g7] ASI_MMU, %g1
+ .previous
+
membar #Sync
mov SECONDARY_CONTEXT, %g7

@@ -269,6 +279,16 @@ after_lock_tlb:
stxa %g0, [%g7] ASI_MMU
.previous

+ /* Restore SECONDARY_CONTEXT_R1, membar should be part of patch */
+ membar #Sync
+661: nop
+ nop
+ .section .sun4v_2insn_patch, "ax"
+ .word 661b
+ mov SECONDARY_CONTEXT_R1, %g7
+ stxa %g1, [%g7] ASI_MMU
+ .previous
+
membar #Sync

/* Everything we do here, until we properly take over the
--
2.7.4