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