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 <linux/threads.h>
9#include <linux/linkage.h>
10
11	.text
12	.import toc_intr,code
13	.import toc_stack,data
14	.align 16
15ENTRY_CFI(toc_handler)
16	load32	PA(toc_stack),%sp
17
18#ifdef CONFIG_SMP
19	/* get per-cpu toc_stack address. */
20	mfctl   %cr30, %r1
21	tophys  %r1,%r2			/* task_struct */
22	LDREG   TASK_TI_CPU(%r2),%r4	/* cpu */
23	load32	PA(__per_cpu_offset),%r1
24	LDREGX  %r4(%r1),%r4
25	add	%r4,%sp,%sp
26#endif
27
28	/*
29	 * setup pt_regs on stack and save the
30	 * floating point registers. PIM_TOC doesn't
31	 * save fp registers, so we're doing it here.
32	 */
33	copy	%sp,%arg0
34	ldo	PT_SZ_ALGN(%sp), %sp
35
36	/* clear pt_regs */
37	copy	%arg0,%r1
380:	cmpb,<<,n %r1,%sp,0b
39	stw,ma	%r0,4(%r1)
40
41	ldo	PT_FR0(%arg0),%r25
42	save_fp	%r25
43
44	/* go virtual */
45	load32	PA(swapper_pg_dir),%r4
46	mtctl	%r4,%cr24
47	mtctl	%r4,%cr25
48
49	/* Clear sr4-sr7 */
50	mtsp	%r0, %sr4
51	mtsp	%r0, %sr5
52	mtsp	%r0, %sr6
53	mtsp	%r0, %sr7
54
55	tovirt_r1 %sp
56	tovirt_r1 %arg0
57	virt_map
58
59	loadgp
60
61#ifdef CONFIG_64BIT
62	ldo	-16(%sp),%r29
63#endif
64	load32	toc_intr,%r1
65	be	0(%sr7,%r1)
66	nop
67ENDPROC_CFI(toc_handler)
68
69	/*
70	 * keep this checksum here, as it is part of the toc_handler
71	 * spanned by toc_handler_size (all words in toc_handler are
72	 * added in PDC and the sum must equal to zero.
73	 */
74SYM_DATA(toc_handler_csum, .long 0)
75SYM_DATA(toc_handler_size, .long . - toc_handler)
76