1/* 2 * This file contains sequences of code that will be copied to a 3 * fixed location, defined in <asm/fixed_code.h>. The interrupt 4 * handlers ensure that these sequences appear to be atomic when 5 * executed from userspace. 6 * These are aligned to 16 bytes, so that we have some space to replace 7 * these sequences with something else (e.g. kernel traps if we ever do 8 * BF561 SMP). 9 * 10 * Copyright 2007-2008 Analog Devices Inc. 11 * 12 * Licensed under the GPL-2 or later. 13 */ 14 15#include <linux/linkage.h> 16#include <linux/init.h> 17#include <linux/unistd.h> 18#include <asm/entry.h> 19 20__INIT 21 22ENTRY(_fixed_code_start) 23 24.align 16 25ENTRY(_sigreturn_stub) 26 P0 = __NR_rt_sigreturn; 27 EXCPT 0; 28 /* Speculative execution paranoia. */ 290: JUMP.S 0b; 30ENDPROC (_sigreturn_stub) 31 32.align 16 33 /* 34 * Atomic swap, 8 bit. 35 * Inputs: P0: memory address to use 36 * R1: value to store 37 * Output: R0: old contents of the memory address, zero extended. 38 */ 39ENTRY(_atomic_xchg32) 40 R0 = [P0]; 41 [P0] = R1; 42 rts; 43ENDPROC (_atomic_xchg32) 44 45.align 16 46 /* 47 * Compare and swap, 32 bit. 48 * Inputs: P0: memory address to use 49 * R1: compare value 50 * R2: new value to store 51 * The new value is stored if the contents of the memory 52 * address is equal to the compare value. 53 * Output: R0: old contents of the memory address. 54 */ 55ENTRY(_atomic_cas32) 56 R0 = [P0]; 57 CC = R0 == R1; 58 IF !CC JUMP 1f; 59 [P0] = R2; 601: 61 rts; 62ENDPROC (_atomic_cas32) 63 64.align 16 65 /* 66 * Atomic add, 32 bit. 67 * Inputs: P0: memory address to use 68 * R0: value to add 69 * Outputs: R0: new contents of the memory address. 70 * R1: previous contents of the memory address. 71 */ 72ENTRY(_atomic_add32) 73 R1 = [P0]; 74 R0 = R1 + R0; 75 [P0] = R0; 76 rts; 77ENDPROC (_atomic_add32) 78 79.align 16 80 /* 81 * Atomic sub, 32 bit. 82 * Inputs: P0: memory address to use 83 * R0: value to subtract 84 * Outputs: R0: new contents of the memory address. 85 * R1: previous contents of the memory address. 86 */ 87ENTRY(_atomic_sub32) 88 R1 = [P0]; 89 R0 = R1 - R0; 90 [P0] = R0; 91 rts; 92ENDPROC (_atomic_sub32) 93 94.align 16 95 /* 96 * Atomic ior, 32 bit. 97 * Inputs: P0: memory address to use 98 * R0: value to ior 99 * Outputs: R0: new contents of the memory address. 100 * R1: previous contents of the memory address. 101 */ 102ENTRY(_atomic_ior32) 103 R1 = [P0]; 104 R0 = R1 | R0; 105 [P0] = R0; 106 rts; 107ENDPROC (_atomic_ior32) 108 109.align 16 110 /* 111 * Atomic and, 32 bit. 112 * Inputs: P0: memory address to use 113 * R0: value to and 114 * Outputs: R0: new contents of the memory address. 115 * R1: previous contents of the memory address. 116 */ 117ENTRY(_atomic_and32) 118 R1 = [P0]; 119 R0 = R1 & R0; 120 [P0] = R0; 121 rts; 122ENDPROC (_atomic_and32) 123 124.align 16 125 /* 126 * Atomic xor, 32 bit. 127 * Inputs: P0: memory address to use 128 * R0: value to xor 129 * Outputs: R0: new contents of the memory address. 130 * R1: previous contents of the memory address. 131 */ 132ENTRY(_atomic_xor32) 133 R1 = [P0]; 134 R0 = R1 ^ R0; 135 [P0] = R0; 136 rts; 137ENDPROC (_atomic_xor32) 138 139.align 16 140 /* 141 * safe_user_instruction 142 * Four NOPS are enough to allow the pipeline to speculativily load 143 * execute anything it wants. After that, things have gone bad, and 144 * we are stuck - so panic. Since we might be in user space, we can't 145 * call panic, so just cause a unhandled exception, this should cause 146 * a dump of the trace buffer so we can tell were we are, and a reboot 147 */ 148ENTRY(_safe_user_instruction) 149 NOP; NOP; NOP; NOP; 150 EXCPT 0x4; 151ENDPROC(_safe_user_instruction) 152 153ENTRY(_fixed_code_end) 154 155__FINIT 156