aboutsummaryrefslogtreecommitdiffstats
path: root/arch/metag/kernel/user_gateway.S
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2012-10-09 10:54:51 +0100
committerJames Hogan <james.hogan@imgtec.com>2013-03-02 20:09:49 +0000
commit26025bbfbba33a9425be1b89eccb4664ea4c17b6 (patch)
treef8a7f754525812c4d758b638d9bcade297af67da /arch/metag/kernel/user_gateway.S
parentmetag: Internal and external irqchips (diff)
downloadlinux-dev-26025bbfbba33a9425be1b89eccb4664ea4c17b6.tar.xz
linux-dev-26025bbfbba33a9425be1b89eccb4664ea4c17b6.zip
metag: System Calls
Add metag system call and gateway page interfaces. The metag architecture port uses the generic system call numbers from asm-generic/unistd.h, as well as a user gateway page mapped at 0x6ffff000 which contains fast atomic primitives (depending on SMP) and a fast method of accessing TLS data. System calls use the SWITCH instruction with the immediate 0x440001 to signal a system call. Signed-off-by: James Hogan <james.hogan@imgtec.com>
Diffstat (limited to '')
-rw-r--r--arch/metag/kernel/user_gateway.S97
1 files changed, 97 insertions, 0 deletions
diff --git a/arch/metag/kernel/user_gateway.S b/arch/metag/kernel/user_gateway.S
new file mode 100644
index 000000000000..7167f3e8db6b
--- /dev/null
+++ b/arch/metag/kernel/user_gateway.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 Imagination Technologies Ltd.
+ *
+ * This file contains code that can be accessed from userspace and can
+ * access certain kernel data structures without the overhead of a system
+ * call.
+ */
+
+#include <asm/metag_regs.h>
+#include <asm/user_gateway.h>
+
+/*
+ * User helpers.
+ *
+ * These are segment of kernel provided user code reachable from user space
+ * at a fixed address in kernel memory. This is used to provide user space
+ * with some operations which require kernel help because of unimplemented
+ * native feature and/or instructions in some Meta CPUs. The idea is for
+ * this code to be executed directly in user mode for best efficiency but
+ * which is too intimate with the kernel counter part to be left to user
+ * libraries. The kernel reserves the right to change this code as needed
+ * without warning. Only the entry points and their results are guaranteed
+ * to be stable.
+ *
+ * Each segment is 64-byte aligned. This mechanism should be used only for
+ * for things that are really small and justified, and not be abused freely.
+ */
+ .text
+ .global ___user_gateway_start
+___user_gateway_start:
+
+ /* get_tls
+ * Offset: 0
+ * Description: Get the TLS pointer for this process.
+ */
+ .global ___kuser_get_tls
+ .type ___kuser_get_tls,function
+___kuser_get_tls:
+ MOVT D1Ar1,#HI(USER_GATEWAY_PAGE + USER_GATEWAY_TLS)
+ ADD D1Ar1,D1Ar1,#LO(USER_GATEWAY_PAGE + USER_GATEWAY_TLS)
+ MOV D1Ar3,TXENABLE
+ AND D1Ar3,D1Ar3,#(TXENABLE_THREAD_BITS)
+ LSR D1Ar3,D1Ar3,#(TXENABLE_THREAD_S - 2)
+ GETD D0Re0,[D1Ar1+D1Ar3]
+___kuser_get_tls_end: /* Beyond this point the read will complete */
+ MOV PC,D1RtP
+ .size ___kuser_get_tls,.-___kuser_get_tls
+ .global ___kuser_get_tls_end
+
+ /* cmpxchg
+ * Offset: 64
+ * Description: Replace the value at 'ptr' with 'newval' if the current
+ * value is 'oldval'. Return zero if we succeeded,
+ * non-zero otherwise.
+ *
+ * Reference prototype:
+ *
+ * int __kuser_cmpxchg(int oldval, int newval, unsigned long *ptr)
+ *
+ */
+ .balign 64
+ .global ___kuser_cmpxchg
+ .type ___kuser_cmpxchg,function
+___kuser_cmpxchg:
+#ifdef CONFIG_SMP
+ /*
+ * We must use LNKGET/LNKSET with an SMP kernel because the other method
+ * does not provide atomicity across multiple CPUs.
+ */
+0: LNKGETD D0Re0,[D1Ar3]
+ CMP D0Re0,D1Ar1
+ LNKSETDZ [D1Ar3],D0Ar2
+ BNZ 1f
+ DEFR D0Re0,TXSTAT
+ ANDT D0Re0,D0Re0,#HI(0x3f000000)
+ CMPT D0Re0,#HI(0x02000000)
+ BNE 0b
+#ifdef CONFIG_METAG_LNKGET_AROUND_CACHE
+ DCACHE [D1Ar3], D0Re0
+#endif
+1: MOV D0Re0,#1
+ XORZ D0Re0,D0Re0,D0Re0
+ MOV PC,D1RtP
+#else
+ GETD D0Re0,[D1Ar3]
+ CMP D0Re0,D1Ar1
+ SETDZ [D1Ar3],D0Ar2
+___kuser_cmpxchg_end: /* Beyond this point the write will complete */
+ MOV D0Re0,#1
+ XORZ D0Re0,D0Re0,D0Re0
+ MOV PC,D1RtP
+#endif /* CONFIG_SMP */
+ .size ___kuser_cmpxchg,.-___kuser_cmpxchg
+ .global ___kuser_cmpxchg_end
+
+ .global ___user_gateway_end
+___user_gateway_end: