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