linux-stable/arch/parisc/kernel/toc_asm.S
Helge Deller d6ab9fc745 parisc: Enable TOC (transfer of contents) feature unconditionally
Before this patch, the TOC code used a pre-allocated stack of 16kb for
each possible CPU. That space overhead was the reason why the TOC
feature wasn't enabled by default for 32-bit kernels.

This patch rewrites the TOC code to use a per-cpu stack. That way we use
much less memory now and as such we enable the TOC feature by default on
all kernels.

Additionally the dump of the registers and the stacktrace wasn't
serialized, which led to multiple CPUs printing the stack backtrace at
once which rendered the output unreadable.
Now the backtraces are nicely serialized by a lock.

Signed-off-by: Helge Deller <deller@gmx.de>
2022-01-11 11:57:37 +01:00

75 lines
1.4 KiB
ArmAsm

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