/* * This file contains sequences of code that will be copied to a * fixed location, defined in <asm/fixed_code.h>. The interrupt * handlers ensure that these sequences appear to be atomic when * executed from userspace. * These are aligned to 16 bytes, so that we have some space to replace * these sequences with something else (e.g. kernel traps if we ever do * BF561 SMP). * * Copyright 2007-2008 Analog Devices Inc. * * Licensed under the GPL-2 or later. */#include <linux/linkage.h>#include <linux/init.h>#include <linux/unistd.h>#include <asm/entry.h>__INITENTRY(_fixed_code_start).align 16ENTRY(_sigreturn_stub) P0 = __NR_rt_sigreturn; EXCPT 0; /* Speculative execution paranoia. */0: JUMP.S 0b;ENDPROC (_sigreturn_stub).align 16 /* * Atomic swap, 8 bit. * Inputs: P0: memory address to use * R1: value to store * Output: R0: old contents of the memory address, zero extended. */ENTRY(_atomic_xchg32) R0 = [P0]; [P0] = R1; rts;ENDPROC (_atomic_xchg32).align 16 /* * Compare and swap, 32 bit. * Inputs: P0: memory address to use * R1: compare value * R2: new value to store * The new value is stored if the contents of the memory * address is equal to the compare value. * Output: R0: old contents of the memory address. */ENTRY(_atomic_cas32) R0 = [P0]; CC = R0 == R1; IF !CC JUMP 1f; [P0] = R2;1: rts;ENDPROC (_atomic_cas32).align 16 /* * Atomic add, 32 bit. * Inputs: P0: memory address to use * R0: value to add * Outputs: R0: new contents of the memory address. * R1: previous contents of the memory address. */ENTRY(_atomic_add32) R1 = [P0]; R0 = R1 + R0; [P0] = R0; rts;ENDPROC (_atomic_add32).align 16 /* * Atomic sub, 32 bit. * Inputs: P0: memory address to use * R0: value to subtract * Outputs: R0: new contents of the memory address. * R1: previous contents of the memory address. */ENTRY(_atomic_sub32) R1 = [P0]; R0 = R1 - R0; [P0] = R0; rts;ENDPROC (_atomic_sub32).align 16 /* * Atomic ior, 32 bit. * Inputs: P0: memory address to use * R0: value to ior * Outputs: R0: new contents of the memory address. * R1: previous contents of the memory address. */ENTRY(_atomic_ior32) R1 = [P0]; R0 = R1 | R0; [P0] = R0; rts;ENDPROC (_atomic_ior32).align 16 /* * Atomic and, 32 bit. * Inputs: P0: memory address to use * R0: value to and * Outputs: R0: new contents of the memory address. * R1: previous contents of the memory address. */ENTRY(_atomic_and32) R1 = [P0]; R0 = R1 & R0; [P0] = R0; rts;ENDPROC (_atomic_and32).align 16 /* * Atomic xor, 32 bit. * Inputs: P0: memory address to use * R0: value to xor * Outputs: R0: new contents of the memory address. * R1: previous contents of the memory address. */ENTRY(_atomic_xor32) R1 = [P0]; R0 = R1 ^ R0; [P0] = R0; rts;ENDPROC (_atomic_xor32).align 16 /* * safe_user_instruction * Four NOPS are enough to allow the pipeline to speculativily load * execute anything it wants. After that, things have gone bad, and * we are stuck - so panic. Since we might be in user space, we can't * call panic, so just cause a unhandled exception, this should cause * a dump of the trace buffer so we can tell were we are, and a reboot */ENTRY(_safe_user_instruction) NOP; NOP; NOP; NOP; EXCPT 0x4;ENDPROC(_safe_user_instruction)ENTRY(_fixed_code_end)__FINIT
/*
* This file contains sequences of code that will be copied to a
* fixed location, defined in <asm/fixed_code.h>. The interrupt
* handlers ensure that these sequences appear to be atomic when
* executed from userspace.
* These are aligned to 16 bytes, so that we have some space to replace
* these sequences with something else (e.g. kernel traps if we ever do
* BF561 SMP).
*
* Copyright 2007-2008 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/unistd.h>
#include <asm/entry.h>
__INIT
ENTRY(_fixed_code_start)
.align 16
ENTRY(_sigreturn_stub)
P0 = __NR_rt_sigreturn;
EXCPT 0;
/* Speculative execution paranoia. */
0: JUMP.S 0b;
ENDPROC (_sigreturn_stub)
.align 16
/*
* Atomic swap, 8 bit.
* Inputs: P0: memory address to use
* R1: value to store
* Output: R0: old contents of the memory address, zero extended.
*/
ENTRY(_atomic_xchg32)
R0 = [P0];
[P0] = R1;
rts;
ENDPROC (_atomic_xchg32)
.align 16
/*
* Compare and swap, 32 bit.
* Inputs: P0: memory address to use
* R1: compare value
* R2: new value to store
* The new value is stored if the contents of the memory
* address is equal to the compare value.
* Output: R0: old contents of the memory address.
*/
ENTRY(_atomic_cas32)
R0 = [P0];
CC = R0 == R1;
IF !CC JUMP 1f;
[P0] = R2;
1:
rts;
ENDPROC (_atomic_cas32)
.align 16
/*
* Atomic add, 32 bit.
* Inputs: P0: memory address to use
* R0: value to add
* Outputs: R0: new contents of the memory address.
* R1: previous contents of the memory address.
*/
ENTRY(_atomic_add32)
R1 = [P0];
R0 = R1 + R0;
[P0] = R0;
rts;
ENDPROC (_atomic_add32)
.align 16
/*
* Atomic sub, 32 bit.
* Inputs: P0: memory address to use
* R0: value to subtract
* Outputs: R0: new contents of the memory address.
* R1: previous contents of the memory address.
*/
ENTRY(_atomic_sub32)
R1 = [P0];
R0 = R1 - R0;
[P0] = R0;
rts;
ENDPROC (_atomic_sub32)
.align 16
/*
* Atomic ior, 32 bit.
* Inputs: P0: memory address to use
* R0: value to ior
* Outputs: R0: new contents of the memory address.
* R1: previous contents of the memory address.
*/
ENTRY(_atomic_ior32)
R1 = [P0];
R0 = R1 | R0;
[P0] = R0;
rts;
ENDPROC (_atomic_ior32)
.align 16
/*
* Atomic and, 32 bit.
* Inputs: P0: memory address to use
* R0: value to and
* Outputs: R0: new contents of the memory address.
* R1: previous contents of the memory address.
*/
ENTRY(_atomic_and32)
R1 = [P0];
R0 = R1 & R0;
[P0] = R0;
rts;
ENDPROC (_atomic_and32)
.align 16
/*
* Atomic xor, 32 bit.
* Inputs: P0: memory address to use
* R0: value to xor
* Outputs: R0: new contents of the memory address.
* R1: previous contents of the memory address.
*/
ENTRY(_atomic_xor32)
R1 = [P0];
R0 = R1 ^ R0;
[P0] = R0;
rts;
ENDPROC (_atomic_xor32)
.align 16
/*
* safe_user_instruction
* Four NOPS are enough to allow the pipeline to speculativily load
* execute anything it wants. After that, things have gone bad, and
* we are stuck - so panic. Since we might be in user space, we can't
* call panic, so just cause a unhandled exception, this should cause
* a dump of the trace buffer so we can tell were we are, and a reboot
*/
ENTRY(_safe_user_instruction)
NOP; NOP; NOP; NOP;
EXCPT 0x4;
ENDPROC(_safe_user_instruction)
ENTRY(_fixed_code_end)
__FINIT