From acdd40e01a98e2c4bf477d5d66c183716e7562c5 Mon Sep 17 00:00:00 2001
From: "David S. Miller" <davem@davemloft.net>
Date: Mon, 7 Nov 2016 08:27:05 -0800
Subject: [PATCH] sparc64: Add CAS emulation trap.
Older 32-bit sparc cpus (other than LEON) lack a CAS instruction, so
we need to provide some kind of helper infrastructure in the kernel
to emulate it.
This is the first part which firstly defines the basic infrastructure
and the simplest implementation, which is to just directly execute the
instruction on sparc64.
We make use of the window fill/spill fault unwind facilities to make
this as simple as possible. When we take a full TSB miss, we check if
the trap level is greater than one, and if so unwind the trap to one
of the final 3 instructions of the interrupted trap handler's block.
Which of the three to use is based upon whether this is a real fault,
an unaligned access, or a data access exception (ie. bus error).
Signed-off-by: David S. Miller <davem@davemloft.net>
---
arch/sparc/include/uapi/asm/unistd.h | 1 +
arch/sparc/kernel/Makefile | 1 +
arch/sparc/kernel/casemul.S | 66 ++++++++++++++++++++++++++++++++++++
arch/sparc/kernel/sys_sparc_64.c | 2 +-
arch/sparc/kernel/ttable_64.S | 3 +-
5 files changed, 71 insertions(+), 2 deletions(-)
create mode 100644 arch/sparc/kernel/casemul.S
@@ -430,6 +430,7 @@
/* Bitmask values returned from kern_features system call. */
#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001
+#define KERN_FEATURE_CAS_EMUL 0x00000002
#ifdef __32bit_syscall_numbers__
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg
CFLAGS_REMOVE_pcr.o := -pg
endif
+obj-$(CONFIG_SPARC64) += casemul.o
obj-$(CONFIG_SPARC64) += urtt_fill.o
obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o
obj-$(CONFIG_SPARC32) += etrap_32.o
new file mode 100644
@@ -0,0 +1,66 @@
+#include <asm/asi.h>
+#include <asm/thread_info.h>
+#include <asm/trap_block.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+
+ .text
+ .align 128
+ .globl emulate_cas
+ .type emulate_cas,#function
+emulate_cas:
+ casa [%o0] ASI_AIUP, %o1, %o2
+ done
+ nop; nop; nop; nop; nop; nop;
+ nop; nop; nop; nop; nop; nop; nop; nop
+ nop; nop; nop; nop; nop; nop; nop; nop
+ nop; nop; nop; nop; nop;
+ ba,a,pt %xcc, 3f
+ ba,a,pt %xcc, 2f
+ ba,a,pt %xcc, 1f
+ .size emulate_cas,.-emulate_cas
+
+ /* Fault */
+1: TRAP_LOAD_THREAD_REG(%g6, %g1)
+ stb %g4, [%g6 + TI_FAULT_CODE]
+ stx %g5, [%g6 + TI_FAULT_ADDR]
+ ba,pt %xcc, etrap
+ rd %pc, %g7
+ call do_sparc64_fault
+ add %sp, PTREGS_OFF, %o0
+ ba,a,pt %xcc, rtrap
+
+ /* Memory address unaligned */
+2: ba,pt %xcc, etrap
+ rd %pc, %g7
+ sethi %hi(tlb_type), %g1
+ lduw [%g1 + %lo(tlb_type)], %g1
+ cmp %g1, 3
+ bne,pt %icc, 1f
+ add %sp, PTREGS_OFF, %o0
+ mov %l4, %o2
+ call sun4v_do_mna
+ mov %l5, %o1
+ ba,a,pt %xcc, rtrap
+1: mov %l4, %o1
+ mov %l5, %o2
+ call mem_address_unaligned
+ nop
+ ba,a,pt %xcc, rtrap
+
+ /* Data access exception */
+3: ba,pt %xcc, etrap
+ rd %pc, %g7
+ sethi %hi(tlb_type), %g1
+ mov %l4, %o1
+ lduw [%g1 + %lo(tlb_type)], %g1
+ mov %l5, %o2
+ cmp %g1, 3
+ bne,pt %icc, 1f
+ add %sp, PTREGS_OFF, %o0
+ call sun4v_data_access_exception
+ nop
+ ba,a,pt %xcc, rtrap
+1: call spitfire_data_access_exception
+ nop
+ ba,a,pt %xcc, rtrap
@@ -643,5 +643,5 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
asmlinkage long sys_kern_features(void)
{
- return KERN_FEATURE_MIXED_MODE_STACK;
+ return KERN_FEATURE_MIXED_MODE_STACK | KERN_FEATURE_CAS_EMUL;
}
@@ -147,7 +147,8 @@ tl0_resv11e: TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUC
tl0_getcc: GETCC_TRAP
tl0_setcc: SETCC_TRAP
tl0_getpsr: TRAP(do_getpsr)
-tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) BTRAP(0x127)
+tl0_cas: TRAP_NOSAVE(emulate_cas)
+tl0_resv124: BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) BTRAP(0x127)
tl0_resv128: BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c)
tl0_resv12d: BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131)
tl0_resv132: BTRAP(0x132) BTRAP(0x133) BTRAP(0x134) BTRAP(0x135) BTRAP(0x136)
--
2.1.2.532.g19b5d50