]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/metag/kernel/user_gateway.S
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[mirror_ubuntu-bionic-kernel.git] / arch / metag / kernel / user_gateway.S
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
26025bbf
JH
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: