1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
5 * Licensed under the GNU GPL.
6 * thanks to Philipp Rumpf, Mike Shaver and various others
7 * sorry about the wall, puffin..
8 */
9
10#include <asm/asm-offsets.h>
11#include <asm/unistd.h>
12#include <asm/errno.h>
13#include <asm/psw.h>
14#include <asm/thread_info.h>
15#include <asm/assembly.h>
16#include <asm/processor.h>
17
18#include <linux/linkage.h>
19
20	/* We fill the empty parts of the gateway page with
21 	 * something that will kill the kernel or a
22 	 * userspace application.
23	 */
24#define KILL_INSN	break	0,0
25
26	.level          LEVEL
27
28	.text
29
30	.import syscall_exit,code
31	.import syscall_exit_rfi,code
32
33	/* Linux gateway page is aliased to virtual page 0 in the kernel
34	 * address space. Since it is a gateway page it cannot be
35	 * dereferenced, so null pointers will still fault. We start
36	 * the actual entry point at 0x100. We put break instructions
37	 * at the beginning of the page to trap null indirect function
38	 * pointers.
39	 */
40
41	.align ASM_PAGE_SIZE
42ENTRY(linux_gateway_page)
43
44        /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
45	.rept 44
46	KILL_INSN
47	.endr
48
49	/* ADDRESS 0xb0 to 0xb4, lws uses 1 insns for entry */
50	/* Light-weight-syscall entry must always be located at 0xb0 */
51	/* WARNING: Keep this number updated with table size changes */
52#define __NR_lws_entries (2)
53
54lws_entry:
55	/* Unconditional branch to lws_start, located on the
56	   same gateway page */
57	b,n	lws_start
58
59	/* Fill from 0xb4 to 0xe0 */
60	.rept 11
61	KILL_INSN
62	.endr
63
64	/* This function MUST be located at 0xe0 for glibc's threading
65	mechanism to work. DO NOT MOVE THIS CODE EVER! */
66set_thread_pointer:
67	gate	.+8, %r0		/* increase privilege */
68	depi	3, 31, 2, %r31		/* Ensure we return into user mode. */
69	be	0(%sr7,%r31)		/* return to user space */
70	mtctl	%r26, %cr27		/* move arg0 to the control register */
71
72	/* Increase the chance of trapping if random jumps occur to this
73	address, fill from 0xf0 to 0x100 */
74	.rept 4
75	KILL_INSN
76	.endr
77
78/* This address must remain fixed at 0x100 for glibc's syscalls to work */
79	.align 256
80linux_gateway_entry:
81	gate	.+8, %r0			/* become privileged */
82	mtsp	%r0,%sr4			/* get kernel space into sr4 */
83	mtsp	%r0,%sr5			/* get kernel space into sr5 */
84	mtsp	%r0,%sr6			/* get kernel space into sr6 */
85	mfsp    %sr7,%r1                        /* save user sr7 */
86	mtsp    %r1,%sr3                        /* and store it in sr3 */
87
88#ifdef CONFIG_64BIT
89	/* for now we can *always* set the W bit on entry to the syscall
90	 * since we don't support wide userland processes.  We could
91	 * also save the current SM other than in r0 and restore it on
92	 * exit from the syscall, and also use that value to know
93	 * whether to do narrow or wide syscalls. -PB
94	 */
95	ssm	PSW_SM_W, %r1
96	extrd,u	%r1,PSW_W_BIT,1,%r1
97	/* sp must be aligned on 4, so deposit the W bit setting into
98	 * the bottom of sp temporarily */
99	or,ev	%r1,%r30,%r30
100	b,n	1f
101	/* The top halves of argument registers must be cleared on syscall
102	 * entry from narrow executable.
103	 */
104	depdi	0, 31, 32, %r26
105	depdi	0, 31, 32, %r25
106	depdi	0, 31, 32, %r24
107	depdi	0, 31, 32, %r23
108	depdi	0, 31, 32, %r22
109	depdi	0, 31, 32, %r21
1101:
111#endif
112	mfctl   %cr30,%r1
113	xor     %r1,%r30,%r30                   /* ye olde xor trick */
114	xor     %r1,%r30,%r1
115	xor     %r1,%r30,%r30
116
117	ldo     THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30  /* set up kernel stack */
118
119	/* N.B.: It is critical that we don't set sr7 to 0 until r30
120	 *       contains a valid kernel stack pointer. It is also
121	 *       critical that we don't start using the kernel stack
122	 *       until after sr7 has been set to 0.
123	 */
124
125	mtsp	%r0,%sr7			/* get kernel space into sr7 */
126	STREGM	%r1,FRAME_SIZE(%r30)		/* save r1 (usp) here for now */
127	mfctl	%cr30,%r1			/* get task ptr in %r1 */
128	LDREG	TI_TASK(%r1),%r1
129
130	/* Save some registers for sigcontext and potential task
131	   switch (see entry.S for the details of which ones are
132	   saved/restored).  TASK_PT_PSW is zeroed so we can see whether
133	   a process is on a syscall or not.  For an interrupt the real
134	   PSW value is stored.  This is needed for gdb and sys_ptrace. */
135	STREG	%r0,  TASK_PT_PSW(%r1)
136	STREG	%r2,  TASK_PT_GR2(%r1)		/* preserve rp */
137	STREG	%r19, TASK_PT_GR19(%r1)
138
139	LDREGM	-FRAME_SIZE(%r30), %r2		/* get users sp back */
140#ifdef CONFIG_64BIT
141	extrd,u	%r2,63,1,%r19			/* W hidden in bottom bit */
142#endif
143	STREG	%r2,  TASK_PT_GR30(%r1)		/* ... and save it */
144
145	STREG	%r20, TASK_PT_GR20(%r1)		/* Syscall number */
146	STREG	%r21, TASK_PT_GR21(%r1)
147	STREG	%r22, TASK_PT_GR22(%r1)
148	STREG	%r23, TASK_PT_GR23(%r1)		/* 4th argument */
149	STREG	%r24, TASK_PT_GR24(%r1)		/* 3rd argument */
150	STREG	%r25, TASK_PT_GR25(%r1)		/* 2nd argument */
151	STREG	%r26, TASK_PT_GR26(%r1)	 	/* 1st argument */
152	STREG	%r27, TASK_PT_GR27(%r1)		/* user dp */
153	STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
154	STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
155	STREG	%r29, TASK_PT_GR29(%r1)		/* return value 1 */
156	STREG	%r31, TASK_PT_GR31(%r1)		/* preserve syscall return ptr */
157
158	ldo	TASK_PT_FR0(%r1), %r27		/* save fpregs from the kernel */
159	save_fp	%r27				/* or potential task switch  */
160
161	mfctl	%cr11, %r27			/* i.e. SAR */
162	STREG	%r27, TASK_PT_SAR(%r1)
163
164	loadgp
165
166#ifdef CONFIG_64BIT
167	ldo	-16(%r30),%r29			/* Reference param save area */
168	copy	%r19,%r2			/* W bit back to r2 */
169#else
170	/* no need to save these on stack in wide mode because the first 8
171	 * args are passed in registers */
172	stw     %r22, -52(%r30)                 /* 5th argument */
173	stw     %r21, -56(%r30)                 /* 6th argument */
174#endif
175
176	/* Are we being ptraced? */
177	mfctl	%cr30, %r1
178	LDREG	TI_TASK(%r1),%r1
179	ldw	TASK_PTRACE(%r1), %r1
180	bb,<,n	%r1,31,.Ltracesys
181
182	/* Note!  We cannot use the syscall table that is mapped
183	nearby since the gateway page is mapped execute-only. */
184
185#ifdef CONFIG_64BIT
186	ldil	L%sys_call_table, %r1
187	or,=	%r2,%r2,%r2
188	addil	L%(sys_call_table64-sys_call_table), %r1
189	ldo	R%sys_call_table(%r1), %r19
190	or,=	%r2,%r2,%r2
191	ldo	R%sys_call_table64(%r1), %r19
192#else
193	ldil	L%sys_call_table, %r1
194	ldo     R%sys_call_table(%r1), %r19
195#endif
196	comiclr,>>	__NR_Linux_syscalls, %r20, %r0
197	b,n	.Lsyscall_nosys
198
199	LDREGX  %r20(%r19), %r19
200
201	/* If this is a sys_rt_sigreturn call, and the signal was received
202	 * when not in_syscall, then we want to return via syscall_exit_rfi,
203	 * not syscall_exit.  Signal no. in r20, in_syscall in r25 (see
204	 * trampoline code in signal.c).
205	 */
206	ldi	__NR_rt_sigreturn,%r2
207	comb,=	%r2,%r20,.Lrt_sigreturn
208.Lin_syscall:
209	ldil	L%syscall_exit,%r2
210	be      0(%sr7,%r19)
211	ldo	R%syscall_exit(%r2),%r2
212.Lrt_sigreturn:
213	comib,<> 0,%r25,.Lin_syscall
214	ldil	L%syscall_exit_rfi,%r2
215	be      0(%sr7,%r19)
216	ldo	R%syscall_exit_rfi(%r2),%r2
217
218	/* Note!  Because we are not running where we were linked, any
219	calls to functions external to this file must be indirect.  To
220	be safe, we apply the opposite rule to functions within this
221	file, with local labels given to them to ensure correctness. */
222
223.Lsyscall_nosys:
224syscall_nosys:
225	ldil	L%syscall_exit,%r1
226	be	R%syscall_exit(%sr7,%r1)
227	ldo	-ENOSYS(%r0),%r28		   /* set errno */
228
229
230/* Warning! This trace code is a virtual duplicate of the code above so be
231 * sure to maintain both! */
232.Ltracesys:
233tracesys:
234	/* Need to save more registers so the debugger can see where we
235	 * are.  This saves only the lower 8 bits of PSW, so that the C
236	 * bit is still clear on syscalls, and the D bit is set if this
237	 * full register save path has been executed.  We check the D
238	 * bit on syscall_return_rfi to determine which registers to
239	 * restore.  An interrupt results in a full PSW saved with the
240	 * C bit set, a non-straced syscall entry results in C and D clear
241	 * in the saved PSW.
242	 */
243	ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
244	LDREG	TI_TASK(%r1), %r1
245	ssm	0,%r2
246	STREG	%r2,TASK_PT_PSW(%r1)		/* Lower 8 bits only!! */
247	mfsp	%sr0,%r2
248	STREG	%r2,TASK_PT_SR0(%r1)
249	mfsp	%sr1,%r2
250	STREG	%r2,TASK_PT_SR1(%r1)
251	mfsp	%sr2,%r2
252	STREG	%r2,TASK_PT_SR2(%r1)
253	mfsp	%sr3,%r2
254	STREG	%r2,TASK_PT_SR3(%r1)
255	STREG	%r2,TASK_PT_SR4(%r1)
256	STREG	%r2,TASK_PT_SR5(%r1)
257	STREG	%r2,TASK_PT_SR6(%r1)
258	STREG	%r2,TASK_PT_SR7(%r1)
259	STREG	%r2,TASK_PT_IASQ0(%r1)
260	STREG	%r2,TASK_PT_IASQ1(%r1)
261	LDREG	TASK_PT_GR31(%r1),%r2
262	STREG	%r2,TASK_PT_IAOQ0(%r1)
263	ldo	4(%r2),%r2
264	STREG	%r2,TASK_PT_IAOQ1(%r1)
265	ldo	TASK_REGS(%r1),%r2
266	/* reg_save %r2 */
267	STREG	%r3,PT_GR3(%r2)
268	STREG	%r4,PT_GR4(%r2)
269	STREG	%r5,PT_GR5(%r2)
270	STREG	%r6,PT_GR6(%r2)
271	STREG	%r7,PT_GR7(%r2)
272	STREG	%r8,PT_GR8(%r2)
273	STREG	%r9,PT_GR9(%r2)
274	STREG	%r10,PT_GR10(%r2)
275	STREG	%r11,PT_GR11(%r2)
276	STREG	%r12,PT_GR12(%r2)
277	STREG	%r13,PT_GR13(%r2)
278	STREG	%r14,PT_GR14(%r2)
279	STREG	%r15,PT_GR15(%r2)
280	STREG	%r16,PT_GR16(%r2)
281	STREG	%r17,PT_GR17(%r2)
282	STREG	%r18,PT_GR18(%r2)
283	/* Finished saving things for the debugger */
284
285	ldil	L%syscall_trace,%r1
286	ldil	L%tracesys_next,%r2
287	be	R%syscall_trace(%sr7,%r1)
288	ldo	R%tracesys_next(%r2),%r2
289
290tracesys_next:
291	ldil	L%sys_call_table,%r1
292	ldo     R%sys_call_table(%r1), %r19
293
294	ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
295	LDREG	TI_TASK(%r1), %r1
296	LDREG   TASK_PT_GR20(%r1), %r20
297	LDREG   TASK_PT_GR26(%r1), %r26		/* Restore the users args */
298	LDREG   TASK_PT_GR25(%r1), %r25
299	LDREG   TASK_PT_GR24(%r1), %r24
300	LDREG   TASK_PT_GR23(%r1), %r23
301#ifdef CONFIG_64BIT
302	LDREG   TASK_PT_GR22(%r1), %r22
303	LDREG   TASK_PT_GR21(%r1), %r21
304	ldo	-16(%r30),%r29			/* Reference param save area */
305#endif
306
307	comiclr,>>=	__NR_Linux_syscalls, %r20, %r0
308	b,n	.Lsyscall_nosys
309
310	LDREGX  %r20(%r19), %r19
311
312	/* If this is a sys_rt_sigreturn call, and the signal was received
313	 * when not in_syscall, then we want to return via syscall_exit_rfi,
314	 * not syscall_exit.  Signal no. in r20, in_syscall in r25 (see
315	 * trampoline code in signal.c).
316	 */
317	ldi	__NR_rt_sigreturn,%r2
318	comb,=	%r2,%r20,.Ltrace_rt_sigreturn
319.Ltrace_in_syscall:
320	ldil	L%tracesys_exit,%r2
321	be      0(%sr7,%r19)
322	ldo	R%tracesys_exit(%r2),%r2
323
324	/* Do *not* call this function on the gateway page, because it
325	makes a direct call to syscall_trace. */
326
327tracesys_exit:
328	ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
329	LDREG	TI_TASK(%r1), %r1
330#ifdef CONFIG_64BIT
331	ldo	-16(%r30),%r29			/* Reference param save area */
332#endif
333	bl	syscall_trace, %r2
334	STREG   %r28,TASK_PT_GR28(%r1)          /* save return value now */
335	ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
336	LDREG	TI_TASK(%r1), %r1
337	LDREG   TASK_PT_GR28(%r1), %r28		/* Restore return val. */
338
339	ldil	L%syscall_exit,%r1
340	be,n	R%syscall_exit(%sr7,%r1)
341
342.Ltrace_rt_sigreturn:
343	comib,<> 0,%r25,.Ltrace_in_syscall
344	ldil	L%tracesys_sigexit,%r2
345	be      0(%sr7,%r19)
346	ldo	R%tracesys_sigexit(%r2),%r2
347
348tracesys_sigexit:
349	ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
350	LDREG	0(%r1), %r1
351#ifdef CONFIG_64BIT
352	ldo	-16(%r30),%r29			/* Reference param save area */
353#endif
354	bl	syscall_trace, %r2
355	nop
356
357	ldil	L%syscall_exit_rfi,%r1
358	be,n	R%syscall_exit_rfi(%sr7,%r1)
359
360
361	/*********************************************************
362		Light-weight-syscall code
363
364		r20 - lws number
365		r26,r25,r24,r23,r22 - Input registers
366		r28 - Function return register
367		r21 - Error code.
368
369		Scracth: Any of the above that aren't being
370		currently used, including r1.
371
372		Return pointer: r31 (Not usable)
373
374		Error codes returned by entry path:
375
376		ENOSYS - r20 was an invalid LWS number.
377
378	*********************************************************/
379lws_start:
380	/* Gate and ensure we return to userspace */
381	gate	.+8, %r0
382	depi	3, 31, 2, %r31	/* Ensure we return to userspace */
383
384#ifdef CONFIG_64BIT
385	ssm	PSW_SM_W, %r1
386	extrd,u	%r1,PSW_W_BIT,1,%r1
387	/* sp must be aligned on 4, so deposit the W bit setting into
388	 * the bottom of sp temporarily */
389	or,ev	%r1,%r30,%r30
390
391	/* Clip LWS number to a 32-bit value always */
392	depdi	0, 31, 32, %r20
393#endif
394
395        /* Is the lws entry number valid? */
396	comiclr,>>=	__NR_lws_entries, %r20, %r0
397	b,n	lws_exit_nosys
398
399	/* WARNING: Trashing sr2 and sr3 */
400	mfsp	%sr7,%r1			/* get userspace into sr3 */
401	mtsp	%r1,%sr3
402	mtsp	%r0,%sr2			/* get kernel space into sr2 */
403
404	/* Load table start */
405	ldil	L%lws_table, %r1
406	ldo	R%lws_table(%r1), %r28	/* Scratch use of r28 */
407	LDREGX	%r20(%sr2,r28), %r21	/* Scratch use of r21 */
408
409	/* Jump to lws, lws table pointers already relocated */
410	be,n	0(%sr2,%r21)
411
412lws_exit_nosys:
413	ldo	-ENOSYS(%r0),%r21		   /* set errno */
414	/* Fall through: Return to userspace */
415
416lws_exit:
417#ifdef CONFIG_64BIT
418	/* decide whether to reset the wide mode bit
419	 *
420	 * For a syscall, the W bit is stored in the lowest bit
421	 * of sp.  Extract it and reset W if it is zero */
422	extrd,u,*<>	%r30,63,1,%r1
423	rsm	PSW_SM_W, %r0
424	/* now reset the lowest bit of sp if it was set */
425	xor	%r30,%r1,%r30
426#endif
427	be,n	0(%sr3, %r31)
428
429
430
431	/***************************************************
432		Implementing CAS as an atomic operation:
433
434		%r26 - Address to examine
435		%r25 - Old value to check (old)
436		%r24 - New value to set (new)
437		%r28 - Return prev through this register.
438		%r21 - Kernel error code
439
440		If debugging is DISabled:
441
442		%r21 has the following meanings:
443
444		EAGAIN - CAS is busy, ldcw failed, try again.
445		EFAULT - Read or write failed.
446
447		If debugging is enabled:
448
449		EDEADLOCK - CAS called recursively.
450		EAGAIN && r28 == 1 - CAS is busy. Lock contended.
451		EAGAIN && r28 == 2 - CAS is busy. ldcw failed.
452		EFAULT - Read or write failed.
453
454		Scratch: r20, r28, r1
455
456	****************************************************/
457
458	/* Do not enable LWS debugging */
459#define ENABLE_LWS_DEBUG 0
460
461	/* ELF64 Process entry path */
462lws_compare_and_swap64:
463#ifdef CONFIG_64BIT
464	b,n	lws_compare_and_swap
465#else
466	/* If we are not a 64-bit kernel, then we don't
467	 * implement having 64-bit input registers
468	 */
469	b,n	lws_exit_nosys
470#endif
471
472	/* ELF32 Process entry path */
473lws_compare_and_swap32:
474#ifdef CONFIG_64BIT
475	/* Clip all the input registers */
476	depdi	0, 31, 32, %r26
477	depdi	0, 31, 32, %r25
478	depdi	0, 31, 32, %r24
479#endif
480
481lws_compare_and_swap:
482#ifdef CONFIG_SMP
483	/* Load start of lock table */
484	ldil	L%lws_lock_start, %r20
485	ldo	R%lws_lock_start(%r20), %r28
486
487	/* Extract four bits from r26 and hash lock (Bits 4-7) */
488	extru  %r26, 27, 4, %r20
489
490	/* Find lock to use, the hash is either one of 0 to
491	   15, multiplied by 16 (keep it 16-byte aligned)
492	   and add to the lock table offset. */
493	shlw	%r20, 4, %r20
494	add	%r20, %r28, %r20
495
496# if ENABLE_LWS_DEBUG
497	/*
498		DEBUG, check for deadlock!
499		If the thread register values are the same
500		then we were the one that locked it last and
501		this is a recurisve call that will deadlock.
502		We *must* giveup this call and fail.
503	*/
504	ldw	4(%sr2,%r20), %r28			/* Load thread register */
505	/* WARNING: If cr27 cycles to the same value we have problems */
506	mfctl	%cr27, %r21				/* Get current thread register */
507	cmpb,<>,n	%r21, %r28, cas_lock		/* Called recursive? */
508	b	lws_exit				/* Return error! */
509	ldo	-EDEADLOCK(%r0), %r21
510cas_lock:
511	cmpb,=,n	%r0, %r28, cas_nocontend	/* Is nobody using it? */
512	ldo	1(%r0), %r28				/* 1st case */
513	b	lws_exit				/* Contended... */
514	ldo	-EAGAIN(%r0), %r21			/* Spin in userspace */
515cas_nocontend:
516# endif
517/* ENABLE_LWS_DEBUG */
518
519	LDCW	0(%sr2,%r20), %r28			/* Try to acquire the lock */
520	cmpb,<>,n	%r0, %r28, cas_action		/* Did we get it? */
521cas_wouldblock:
522	ldo	2(%r0), %r28				/* 2nd case */
523	b	lws_exit				/* Contended... */
524	ldo	-EAGAIN(%r0), %r21			/* Spin in userspace */
525#endif
526/* CONFIG_SMP */
527
528	/*
529		prev = *addr;
530		if ( prev == old )
531		  *addr = new;
532		return prev;
533	*/
534
535	/* NOTES:
536		This all works becuse intr_do_signal
537		and schedule both check the return iasq
538		and see that we are on the kernel page
539		so this process is never scheduled off
540		or is ever sent any signal of any sort,
541		thus it is wholly atomic from usrspaces
542		perspective
543	*/
544cas_action:
545#if defined CONFIG_SMP && ENABLE_LWS_DEBUG
546	/* DEBUG */
547	mfctl	%cr27, %r1
548	stw	%r1, 4(%sr2,%r20)
549#endif
550	/* The load and store could fail */
5511:	ldw	0(%sr3,%r26), %r28
552	sub,<>	%r28, %r25, %r0
5532:	stw	%r24, 0(%sr3,%r26)
554#ifdef CONFIG_SMP
555	/* Free lock */
556	stw	%r20, 0(%sr2,%r20)
557# if ENABLE_LWS_DEBUG
558	/* Clear thread register indicator */
559	stw	%r0, 4(%sr2,%r20)
560# endif
561#endif
562	/* Return to userspace, set no error */
563	b	lws_exit
564	copy	%r0, %r21
565
5663:
567	/* Error occured on load or store */
568#ifdef CONFIG_SMP
569	/* Free lock */
570	stw	%r20, 0(%sr2,%r20)
571# if ENABLE_LWS_DEBUG
572	stw	%r0, 4(%sr2,%r20)
573# endif
574#endif
575	b	lws_exit
576	ldo	-EFAULT(%r0),%r21	/* set errno */
577	nop
578	nop
579	nop
580	nop
581
582	/* Two exception table entries, one for the load,
583	   the other for the store. Either return -EFAULT.
584	   Each of the entries must be relocated. */
585	.section __ex_table,"aw"
586	ASM_ULONG_INSN (1b - linux_gateway_page), (3b - linux_gateway_page)
587	ASM_ULONG_INSN (2b - linux_gateway_page), (3b - linux_gateway_page)
588	.previous
589
590
591	/* Make sure nothing else is placed on this page */
592	.align ASM_PAGE_SIZE
593END(linux_gateway_page)
594ENTRY(end_linux_gateway_page)
595
596	/* Relocate symbols assuming linux_gateway_page is mapped
597	   to virtual address 0x0 */
598
599#define LWS_ENTRY(_name_) ASM_ULONG_INSN (lws_##_name_ - linux_gateway_page)
600
601	.section .rodata,"a"
602
603	.align ASM_PAGE_SIZE
604	/* Light-weight-syscall table */
605	/* Start of lws table. */
606ENTRY(lws_table)
607	LWS_ENTRY(compare_and_swap32)	/* 0 - ELF32 Atomic compare and swap */
608	LWS_ENTRY(compare_and_swap64)	/* 1 - ELF64 Atomic compare and swap */
609END(lws_table)
610	/* End of lws table */
611
612	.align ASM_PAGE_SIZE
613ENTRY(sys_call_table)
614#include "syscall_table.S"
615END(sys_call_table)
616
617#ifdef CONFIG_64BIT
618	.align ASM_PAGE_SIZE
619ENTRY(sys_call_table64)
620#define SYSCALL_TABLE_64BIT
621#include "syscall_table.S"
622END(sys_call_table64)
623#endif
624
625#ifdef CONFIG_SMP
626	/*
627		All light-weight-syscall atomic operations
628		will use this set of locks
629	*/
630	.section .data
631	.align 4096
632ENTRY(lws_lock_start)
633	/* lws locks */
634	.align 16
635	.rept 16
636	/* Keep locks aligned at 16-bytes */
637	.word 1
638	.word 0
639	.word 0
640	.word 0
641	.endr
642END(lws_lock_start)
643	.previous
644#endif
645/* CONFIG_SMP for lws_lock_start */
646
647.end
648