diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-03 12:06:09 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-03 12:06:09 -0800 |
commit | 8fd5e7a2d9574b3cac1c9264ad1aed3b613ed6fe (patch) | |
tree | 5696f5d31c6c75b71bfc4852fb234b773e266cfe /arch/metag/kernel/user_gateway.S | |
parent | 529e5fbcd8d3cb48cf824ac8fde91cc80a9e985f (diff) | |
parent | c60ac31542e93499b58dcfc1e3f6550ba5b5728e (diff) |
Merge tag 'metag-v3.9-rc1-v4' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag
Pull new ImgTec Meta architecture from James Hogan:
"This adds core architecture support for Imagination's Meta processor
cores, followed by some later miscellaneous arch/metag cleanups and
fixes which I kept separate to ease review:
- Support for basic Meta 1 (ATP) and Meta 2 (HTP) core architecture
- A few fixes all over, particularly for symbol prefixes
- A few privilege protection fixes
- Several cleanups (setup.c includes, split out a lot of
metag_ksyms.c)
- Fix some missing exports
- Convert hugetlb to use vm_unmapped_area()
- Copy device tree to non-init memory
- Provide dma_get_sgtable()"
* tag 'metag-v3.9-rc1-v4' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag: (61 commits)
metag: Provide dma_get_sgtable()
metag: prom.h: remove declaration of metag_dt_memblock_reserve()
metag: copy devicetree to non-init memory
metag: cleanup metag_ksyms.c includes
metag: move mm/init.c exports out of metag_ksyms.c
metag: move usercopy.c exports out of metag_ksyms.c
metag: move setup.c exports out of metag_ksyms.c
metag: move kick.c exports out of metag_ksyms.c
metag: move traps.c exports out of metag_ksyms.c
metag: move irq enable out of irqflags.h on SMP
genksyms: fix metag symbol prefix on crc symbols
metag: hugetlb: convert to vm_unmapped_area()
metag: export clear_page and copy_page
metag: export metag_code_cache_flush_all
metag: protect more non-MMU memory regions
metag: make TXPRIVEXT bits explicit
metag: kernel/setup.c: sort includes
perf: Enable building perf tools for Meta
metag: add boot time LNKGET/LNKSET check
metag: add __init to metag_cache_probe()
...
Diffstat (limited to 'arch/metag/kernel/user_gateway.S')
-rw-r--r-- | arch/metag/kernel/user_gateway.S | 97 |
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: |