• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2010 Imagination Technologies Ltd.
4 *
5 * This file contains code that can be accessed from userspace and can
6 * access certain kernel data structures without the overhead of a system
7 * call.
8 */
9
10#include <asm/metag_regs.h>
11#include <asm/user_gateway.h>
12
13/*
14 * User helpers.
15 *
16 * These are segment of kernel provided user code reachable from user space
17 * at a fixed address in kernel memory.  This is used to provide user space
18 * with some operations which require kernel help because of unimplemented
19 * native feature and/or instructions in some Meta CPUs. The idea is for
20 * this code to be executed directly in user mode for best efficiency but
21 * which is too intimate with the kernel counter part to be left to user
22 * libraries.  The kernel reserves the right to change this code as needed
23 * without warning. Only the entry points and their results are guaranteed
24 * to be stable.
25 *
26 * Each segment is 64-byte aligned.  This mechanism should be used only for
27 * for things that are really small and justified, and not be abused freely.
28 */
29	.text
30	.global	___user_gateway_start
31___user_gateway_start:
32
33	/* get_tls
34	 * Offset:	 0
35	 * Description:	 Get the TLS pointer for this process.
36	 */
37	.global	___kuser_get_tls
38	.type	___kuser_get_tls,function
39___kuser_get_tls:
40	MOVT	D1Ar1,#HI(USER_GATEWAY_PAGE + USER_GATEWAY_TLS)
41	ADD	D1Ar1,D1Ar1,#LO(USER_GATEWAY_PAGE + USER_GATEWAY_TLS)
42	MOV	D1Ar3,TXENABLE
43	AND	D1Ar3,D1Ar3,#(TXENABLE_THREAD_BITS)
44	LSR	D1Ar3,D1Ar3,#(TXENABLE_THREAD_S - 2)
45	GETD	D0Re0,[D1Ar1+D1Ar3]
46___kuser_get_tls_end:		/* Beyond this point the read will complete */
47	MOV	PC,D1RtP
48	.size	___kuser_get_tls,.-___kuser_get_tls
49	.global	___kuser_get_tls_end
50
51	/* cmpxchg
52	 * Offset:	 64
53	 * Description:  Replace the value at 'ptr' with 'newval' if the current
54	 *		 value is 'oldval'. Return zero if we succeeded,
55	 *		 non-zero otherwise.
56	 *
57	 * Reference prototype:
58	 *
59	 *	int __kuser_cmpxchg(int oldval, int newval, unsigned long *ptr)
60	 *
61	 */
62	.balign 64
63	.global ___kuser_cmpxchg
64	.type   ___kuser_cmpxchg,function
65___kuser_cmpxchg:
66#ifdef CONFIG_SMP
67	/*
68	 * We must use LNKGET/LNKSET with an SMP kernel because the other method
69	 * does not provide atomicity across multiple CPUs.
70	 */
710:	LNKGETD	D0Re0,[D1Ar3]
72	CMP	D0Re0,D1Ar1
73	LNKSETDZ [D1Ar3],D0Ar2
74	BNZ	1f
75	DEFR	D0Re0,TXSTAT
76	ANDT	D0Re0,D0Re0,#HI(0x3f000000)
77	CMPT	D0Re0,#HI(0x02000000)
78	BNE	0b
79#ifdef CONFIG_METAG_LNKGET_AROUND_CACHE
80	DCACHE  [D1Ar3], D0Re0
81#endif
821:	MOV	D0Re0,#1
83	XORZ	D0Re0,D0Re0,D0Re0
84	MOV	PC,D1RtP
85#else
86	GETD	D0Re0,[D1Ar3]
87	CMP	D0Re0,D1Ar1
88	SETDZ	[D1Ar3],D0Ar2
89___kuser_cmpxchg_end:		/* Beyond this point the write will complete */
90	MOV	D0Re0,#1
91	XORZ	D0Re0,D0Re0,D0Re0
92	MOV	PC,D1RtP
93#endif /* CONFIG_SMP */
94	.size	___kuser_cmpxchg,.-___kuser_cmpxchg
95	.global	___kuser_cmpxchg_end
96
97	.global	___user_gateway_end
98___user_gateway_end:
99