xref: /linux/arch/parisc/kernel/toc_asm.S (revision 448cc2fb3a7b327823a9afd374808c37b8e6194f)
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3/* TOC (Transfer of Control) handler. */
4
5	.level 1.1
6
7#include <asm/assembly.h>
8#include <asm/psw.h>
9#include <linux/threads.h>
10#include <linux/linkage.h>
11
12	.text
13	.import toc_intr,code
14	.import toc_lock,data
15	.align 16
16ENTRY_CFI(toc_handler)
17	/*
18	 * synchronize CPUs and obtain offset
19	 * for stack setup.
20	 */
21	load32		PA(toc_lock),%r1
220:	ldcw,co		0(%r1),%r2
23	cmpib,=		0,%r2,0b
24	nop
25	addi		1,%r2,%r4
26	stw		%r4,0(%r1)
27	addi		-1,%r2,%r4
28
29	load32	PA(toc_stack),%sp
30	/*
31	 * deposit CPU number into stack address,
32	 * so every CPU will have its own stack.
33	 */
34	SHLREG	%r4,14,%r4
35	add	%r4,%sp,%sp
36
37	/*
38	 * setup pt_regs on stack and save the
39	 * floating point registers. PIM_TOC doesn't
40	 * save fp registers, so we're doing it here.
41	 */
42	copy	%sp,%arg0
43	ldo	PT_SZ_ALGN(%sp), %sp
44
45	/* clear pt_regs */
46	copy	%arg0,%r1
470:	cmpb,<<,n %r1,%sp,0b
48	stw,ma	%r0,4(%r1)
49
50	ldo	PT_FR0(%arg0),%r25
51	save_fp	%r25
52
53	/* go virtual */
54	load32	PA(swapper_pg_dir),%r4
55	mtctl	%r4,%cr24
56	mtctl	%r4,%cr25
57
58	/* Clear sr4-sr7 */
59	mtsp	%r0, %sr4
60	mtsp	%r0, %sr5
61	mtsp	%r0, %sr6
62	mtsp	%r0, %sr7
63
64	tovirt_r1 %sp
65	tovirt_r1 %arg0
66	virt_map
67
68	loadgp
69
70#ifdef CONFIG_64BIT
71	ldo	-16(%sp),%r29
72#endif
73	load32	toc_intr,%r1
74	be	0(%sr7,%r1)
75	nop
76ENDPROC_CFI(toc_handler)
77
78	/*
79	 * keep this checksum here, as it is part of the toc_handler
80	 * spanned by toc_handler_size (all words in toc_handler are
81	 * added in PDC and the sum must equal to zero.
82	 */
83SYM_DATA(toc_handler_csum, .long 0)
84SYM_DATA(toc_handler_size, .long . - toc_handler)
85
86	__PAGE_ALIGNED_BSS
87	.align 64
88SYM_DATA(toc_stack, .block 16384*NR_CPUS)
89