mirror of
https://github.com/torvalds/linux.git
synced 2024-12-16 16:12:52 +00:00
cb8a2ef084
The kernel CONFIG_UNWINDER_ORC option enables the ORC unwinder, which is similar in concept to a DWARF unwinder. The difference is that the format of the ORC data is much simpler than DWARF, which in turn allows the ORC unwinder to be much simpler and faster. The ORC data consists of unwind tables which are generated by objtool. After analyzing all the code paths of a .o file, it determines information about the stack state at each instruction address in the file and outputs that information to the .orc_unwind and .orc_unwind_ip sections. The per-object ORC sections are combined at link time and are sorted and post-processed at boot time. The unwinder uses the resulting data to correlate instruction addresses with their stack states at run time. Most of the logic are similar with x86, in order to get ra info before ra is saved into stack, add ra_reg and ra_offset into orc_entry. At the same time, modify some arch-specific code to silence the objtool warnings. Co-developed-by: Jinyang He <hejinyang@loongson.cn> Signed-off-by: Jinyang He <hejinyang@loongson.cn> Co-developed-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
113 lines
2.4 KiB
ArmAsm
113 lines
2.4 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* relocate_kernel.S for kexec
|
|
*
|
|
* Copyright (C) 2022 Loongson Technology Corporation Limited
|
|
*/
|
|
|
|
#include <linux/kexec.h>
|
|
|
|
#include <asm/asm.h>
|
|
#include <asm/asmmacro.h>
|
|
#include <asm/regdef.h>
|
|
#include <asm/loongarch.h>
|
|
#include <asm/stackframe.h>
|
|
#include <asm/addrspace.h>
|
|
|
|
SYM_CODE_START(relocate_new_kernel)
|
|
UNWIND_HINT_UNDEFINED
|
|
/*
|
|
* a0: EFI boot flag for the new kernel
|
|
* a1: Command line pointer for the new kernel
|
|
* a2: System table pointer for the new kernel
|
|
* a3: Start address to jump to after relocation
|
|
* a4: Pointer to the current indirection page entry
|
|
*/
|
|
move s0, a4
|
|
|
|
/*
|
|
* In case of a kdump/crash kernel, the indirection page is not
|
|
* populated as the kernel is directly copied to a reserved location
|
|
*/
|
|
beqz s0, done
|
|
|
|
process_entry:
|
|
PTR_L s1, s0, 0
|
|
PTR_ADDI s0, s0, SZREG
|
|
|
|
/* destination page */
|
|
andi s2, s1, IND_DESTINATION
|
|
beqz s2, 1f
|
|
li.w t0, ~0x1
|
|
and s3, s1, t0 /* store destination addr in s3 */
|
|
b process_entry
|
|
|
|
1:
|
|
/* indirection page, update s0 */
|
|
andi s2, s1, IND_INDIRECTION
|
|
beqz s2, 1f
|
|
li.w t0, ~0x2
|
|
and s0, s1, t0
|
|
b process_entry
|
|
|
|
1:
|
|
/* done page */
|
|
andi s2, s1, IND_DONE
|
|
beqz s2, 1f
|
|
b done
|
|
|
|
1:
|
|
/* source page */
|
|
andi s2, s1, IND_SOURCE
|
|
beqz s2, process_entry
|
|
li.w t0, ~0x8
|
|
and s1, s1, t0
|
|
li.w s5, (1 << _PAGE_SHIFT) / SZREG
|
|
|
|
copy_word:
|
|
/* copy page word by word */
|
|
REG_L s4, s1, 0
|
|
REG_S s4, s3, 0
|
|
PTR_ADDI s3, s3, SZREG
|
|
PTR_ADDI s1, s1, SZREG
|
|
LONG_ADDI s5, s5, -1
|
|
beqz s5, process_entry
|
|
b copy_word
|
|
|
|
done:
|
|
ibar 0
|
|
dbar 0
|
|
|
|
/*
|
|
* Jump to the new kernel,
|
|
* make sure the values of a0, a1, a2 and a3 are not changed.
|
|
*/
|
|
jr a3
|
|
SYM_CODE_END(relocate_new_kernel)
|
|
|
|
#ifdef CONFIG_SMP
|
|
/*
|
|
* Other CPUs should wait until code is relocated and
|
|
* then start at the entry point from LOONGARCH_IOCSR_MBUF0.
|
|
*/
|
|
SYM_CODE_START(kexec_smp_wait)
|
|
UNWIND_HINT_UNDEFINED
|
|
1: li.w t0, 0x100 /* wait for init loop */
|
|
2: addi.w t0, t0, -1 /* limit mailbox access */
|
|
bnez t0, 2b
|
|
li.w t1, LOONGARCH_IOCSR_MBUF0
|
|
iocsrrd.w s0, t1 /* check PC as an indicator */
|
|
beqz s0, 1b
|
|
iocsrrd.d s0, t1 /* get PC via mailbox */
|
|
|
|
li.d t0, CACHE_BASE
|
|
or s0, s0, t0 /* s0 = TO_CACHE(s0) */
|
|
jr s0 /* jump to initial PC */
|
|
SYM_CODE_END(kexec_smp_wait)
|
|
#endif
|
|
|
|
relocate_new_kernel_end:
|
|
|
|
.section ".data"
|
|
SYM_DATA(relocate_new_kernel_size, .long relocate_new_kernel_end - relocate_new_kernel)
|