root/arch/parisc/kernel/toc_asm.S
/* SPDX-License-Identifier: GPL-2.0-or-later */

/* TOC (Transfer of Control) handler. */

        .level 1.1

#include <asm/assembly.h>
#include <linux/threads.h>
#include <linux/linkage.h>

        .text
        .import toc_intr,code
        .import toc_stack,data
        .align 16
ENTRY_CFI(toc_handler)
        load32  PA(toc_stack),%sp

#ifdef CONFIG_SMP
        /* get per-cpu toc_stack address. */
        mfctl   %cr30, %r1
        tophys  %r1,%r2                 /* task_struct */
        LDREG   TASK_TI_CPU(%r2),%r4    /* cpu */
        load32  PA(__per_cpu_offset),%r1
        LDREGX  %r4(%r1),%r4
        add     %r4,%sp,%sp
#endif

        /*
         * 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
        virt_map

        loadgp

#ifdef CONFIG_64BIT
        ldo     -16(%sp),%r29
#endif
        load32  toc_intr,%r1
        be      0(%sr7,%r1)
        nop
ENDPROC_CFI(toc_handler)

        /*
         * 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)