Commit | Line | Data |
---|---|---|
7adfb58f BS |
1 | /* |
2 | * This file contains sequences of code that will be copied to a | |
60c05953 | 3 | * fixed location, defined in <asm/fixed_code.h>. The interrupt |
7adfb58f BS |
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). | |
96f1050d RG |
9 | * |
10 | * Copyright 2007-2008 Analog Devices Inc. | |
11 | * | |
12 | * Licensed under the GPL-2 or later. | |
7adfb58f | 13 | */ |
96f1050d | 14 | |
7adfb58f | 15 | #include <linux/linkage.h> |
bda07aac | 16 | #include <linux/init.h> |
1f83b8f1 | 17 | #include <linux/unistd.h> |
7adfb58f | 18 | #include <asm/entry.h> |
7adfb58f | 19 | |
bda07aac MF |
20 | __INIT |
21 | ||
7adfb58f BS |
22 | ENTRY(_fixed_code_start) |
23 | ||
24 | .align 16 | |
25 | ENTRY(_sigreturn_stub) | |
26 | P0 = __NR_rt_sigreturn; | |
27 | EXCPT 0; | |
28 | /* Speculative execution paranoia. */ | |
29 | 0: JUMP.S 0b; | |
30 | ENDPROC (_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 | */ | |
39 | ENTRY(_atomic_xchg32) | |
40 | R0 = [P0]; | |
41 | [P0] = R1; | |
42 | rts; | |
43 | ENDPROC (_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 | */ | |
55 | ENTRY(_atomic_cas32) | |
56 | R0 = [P0]; | |
57 | CC = R0 == R1; | |
58 | IF !CC JUMP 1f; | |
59 | [P0] = R2; | |
60 | 1: | |
61 | rts; | |
62 | ENDPROC (_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 | */ | |
72 | ENTRY(_atomic_add32) | |
73 | R1 = [P0]; | |
74 | R0 = R1 + R0; | |
75 | [P0] = R0; | |
76 | rts; | |
77 | ENDPROC (_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 | */ | |
87 | ENTRY(_atomic_sub32) | |
88 | R1 = [P0]; | |
89 | R0 = R1 - R0; | |
90 | [P0] = R0; | |
91 | rts; | |
92 | ENDPROC (_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 | */ | |
102 | ENTRY(_atomic_ior32) | |
103 | R1 = [P0]; | |
104 | R0 = R1 | R0; | |
105 | [P0] = R0; | |
106 | rts; | |
107 | ENDPROC (_atomic_ior32) | |
108 | ||
109 | .align 16 | |
110 | /* | |
11b0be7c | 111 | * Atomic and, 32 bit. |
7adfb58f | 112 | * Inputs: P0: memory address to use |
11b0be7c | 113 | * R0: value to and |
7adfb58f BS |
114 | * Outputs: R0: new contents of the memory address. |
115 | * R1: previous contents of the memory address. | |
116 | */ | |
117 | ENTRY(_atomic_and32) | |
118 | R1 = [P0]; | |
119 | R0 = R1 & R0; | |
120 | [P0] = R0; | |
121 | rts; | |
11b0be7c | 122 | ENDPROC (_atomic_and32) |
7adfb58f BS |
123 | |
124 | .align 16 | |
125 | /* | |
11b0be7c | 126 | * Atomic xor, 32 bit. |
7adfb58f | 127 | * Inputs: P0: memory address to use |
11b0be7c | 128 | * R0: value to xor |
7adfb58f BS |
129 | * Outputs: R0: new contents of the memory address. |
130 | * R1: previous contents of the memory address. | |
131 | */ | |
132 | ENTRY(_atomic_xor32) | |
133 | R1 = [P0]; | |
134 | R0 = R1 ^ R0; | |
135 | [P0] = R0; | |
136 | rts; | |
11b0be7c | 137 | ENDPROC (_atomic_xor32) |
7adfb58f | 138 | |
9f336a53 RG |
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 | */ | |
148 | ENTRY(_safe_user_instruction) | |
149 | NOP; NOP; NOP; NOP; | |
150 | EXCPT 0x4; | |
151 | ENDPROC(_safe_user_instruction) | |
152 | ||
7adfb58f | 153 | ENTRY(_fixed_code_end) |
bda07aac MF |
154 | |
155 | __FINIT |