blob: e94ba80441906586b9a84e75dcb2ad1d63db5838 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* TOC (Transfer of Control) handler. */
.level 1.1
#include <asm/assembly.h>
#include <asm/psw.h>
#include <linux/threads.h>
#include <linux/linkage.h>
.import toc_intr,code
.import toc_lock,data
.align 16
* synchronize CPUs and obtain offset
* for stack setup.
load32 PA(toc_lock),%r1
0: ldcw,co 0(%r1),%r2
cmpib,= 0,%r2,0b
addi 1,%r2,%r4
stw %r4,0(%r1)
addi -1,%r2,%r4
load32 PA(toc_stack),%sp
* deposit CPU number into stack address,
* so every CPU will have its own stack.
SHLREG %r4,14,%r4
add %r4,%sp,%sp
* setup pt_regs on stack and save the
* floating point registers. PIM_TOC doesn't
* save fp registers, so we're doing it here.
copy %sp,%arg0
ldo PT_SZ_ALGN(%sp), %sp
/* clear pt_regs */
copy %arg0,%r1
0: cmpb,<<,n %r1,%sp,0b
stw,ma %r0,4(%r1)
ldo PT_FR0(%arg0),%r25
save_fp %r25
/* go virtual */
load32 PA(swapper_pg_dir),%r4
mtctl %r4,%cr24
mtctl %r4,%cr25
/* Clear sr4-sr7 */
mtsp %r0, %sr4
mtsp %r0, %sr5
mtsp %r0, %sr6
mtsp %r0, %sr7
tovirt_r1 %sp
tovirt_r1 %arg0
#ifdef CONFIG_64BIT
ldo -16(%sp),%r29
load32 toc_intr,%r1
be 0(%sr7,%r1)
* keep this checksum here, as it is part of the toc_handler
* spanned by toc_handler_size (all words in toc_handler are
* added in PDC and the sum must equal to zero.
SYM_DATA(toc_handler_csum, .long 0)
SYM_DATA(toc_handler_size, .long . - toc_handler)
.align 64
SYM_DATA(toc_stack, .block 16384*NR_CPUS)