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