mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-17 16:14:25 +08:00
4d62e81b60
Giancarlo Ferrari reports the following oops while trying to use kexec: Unable to handle kernel paging request at virtual address 80112f38 pgd = fd7ef03e [80112f38] *pgd=0001141e(bad) Internal error: Oops: 80d [#1] PREEMPT SMP ARM ... This is caused by machine_kexec() trying to set the kernel text to be read/write, so it can poke values into the relocation code before copying it - and an interrupt occuring which changes the page tables. The subsequent writes then hit read-only sections that trigger a data abort resulting in the above oops. Fix this by copying the relocation code, and then writing the variables into the destination, thereby avoiding the need to make the kernel text read/write. Reported-by: Giancarlo Ferrari <giancarlo.ferrari89@gmail.com> Tested-by: Giancarlo Ferrari <giancarlo.ferrari89@gmail.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
180 lines
7.1 KiB
C
180 lines
7.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (C) 1995-2003 Russell King
|
|
* 2001-2002 Keith Owens
|
|
*
|
|
* Generate definitions needed by assembly language modules.
|
|
* This code generates raw asm output which is post-processed to extract
|
|
* and format the required data.
|
|
*/
|
|
#include <linux/compiler.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/kexec-internal.h>
|
|
#include <asm/glue-df.h>
|
|
#include <asm/glue-pf.h>
|
|
#include <asm/mach/arch.h>
|
|
#include <asm/thread_info.h>
|
|
#include <asm/memory.h>
|
|
#include <asm/mpu.h>
|
|
#include <asm/procinfo.h>
|
|
#include <asm/suspend.h>
|
|
#include <asm/vdso_datapage.h>
|
|
#include <asm/hardware/cache-l2x0.h>
|
|
#include <linux/kbuild.h>
|
|
#include "signal.h"
|
|
|
|
/*
|
|
* Make sure that the compiler and target are compatible.
|
|
*/
|
|
#if defined(__APCS_26__)
|
|
#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
|
|
#endif
|
|
|
|
int main(void)
|
|
{
|
|
DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
|
|
#ifdef CONFIG_STACKPROTECTOR
|
|
DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
|
|
#endif
|
|
BLANK();
|
|
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
|
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
|
|
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
|
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
|
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
|
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
|
|
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
|
|
DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp));
|
|
DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
|
|
DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
|
|
#ifdef CONFIG_VFP
|
|
DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
|
|
#ifdef CONFIG_SMP
|
|
DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu));
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_ARM_THUMBEE
|
|
DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state));
|
|
#endif
|
|
#ifdef CONFIG_IWMMXT
|
|
DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
|
|
#endif
|
|
#ifdef CONFIG_CRUNCH
|
|
DEFINE(TI_CRUNCH_STATE, offsetof(struct thread_info, crunchstate));
|
|
#endif
|
|
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
|
|
DEFINE(TI_STACK_CANARY, offsetof(struct thread_info, stack_canary));
|
|
#endif
|
|
DEFINE(THREAD_SZ_ORDER, THREAD_SIZE_ORDER);
|
|
BLANK();
|
|
DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0));
|
|
DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
|
|
DEFINE(S_R2, offsetof(struct pt_regs, ARM_r2));
|
|
DEFINE(S_R3, offsetof(struct pt_regs, ARM_r3));
|
|
DEFINE(S_R4, offsetof(struct pt_regs, ARM_r4));
|
|
DEFINE(S_R5, offsetof(struct pt_regs, ARM_r5));
|
|
DEFINE(S_R6, offsetof(struct pt_regs, ARM_r6));
|
|
DEFINE(S_R7, offsetof(struct pt_regs, ARM_r7));
|
|
DEFINE(S_R8, offsetof(struct pt_regs, ARM_r8));
|
|
DEFINE(S_R9, offsetof(struct pt_regs, ARM_r9));
|
|
DEFINE(S_R10, offsetof(struct pt_regs, ARM_r10));
|
|
DEFINE(S_FP, offsetof(struct pt_regs, ARM_fp));
|
|
DEFINE(S_IP, offsetof(struct pt_regs, ARM_ip));
|
|
DEFINE(S_SP, offsetof(struct pt_regs, ARM_sp));
|
|
DEFINE(S_LR, offsetof(struct pt_regs, ARM_lr));
|
|
DEFINE(S_PC, offsetof(struct pt_regs, ARM_pc));
|
|
DEFINE(S_PSR, offsetof(struct pt_regs, ARM_cpsr));
|
|
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
|
|
DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
|
|
DEFINE(SVC_DACR, offsetof(struct svc_pt_regs, dacr));
|
|
DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit));
|
|
DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs));
|
|
BLANK();
|
|
DEFINE(SIGFRAME_RC3_OFFSET, offsetof(struct sigframe, retcode[3]));
|
|
DEFINE(RT_SIGFRAME_RC3_OFFSET, offsetof(struct rt_sigframe, sig.retcode[3]));
|
|
BLANK();
|
|
#ifdef CONFIG_CACHE_L2X0
|
|
DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base));
|
|
DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl));
|
|
DEFINE(L2X0_R_TAG_LATENCY, offsetof(struct l2x0_regs, tag_latency));
|
|
DEFINE(L2X0_R_DATA_LATENCY, offsetof(struct l2x0_regs, data_latency));
|
|
DEFINE(L2X0_R_FILTER_START, offsetof(struct l2x0_regs, filter_start));
|
|
DEFINE(L2X0_R_FILTER_END, offsetof(struct l2x0_regs, filter_end));
|
|
DEFINE(L2X0_R_PREFETCH_CTRL, offsetof(struct l2x0_regs, prefetch_ctrl));
|
|
DEFINE(L2X0_R_PWR_CTRL, offsetof(struct l2x0_regs, pwr_ctrl));
|
|
BLANK();
|
|
#endif
|
|
#ifdef CONFIG_CPU_HAS_ASID
|
|
DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id.counter));
|
|
BLANK();
|
|
#endif
|
|
DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm));
|
|
DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags));
|
|
BLANK();
|
|
DEFINE(VM_EXEC, VM_EXEC);
|
|
BLANK();
|
|
DEFINE(PAGE_SZ, PAGE_SIZE);
|
|
BLANK();
|
|
DEFINE(SYS_ERROR0, 0x9f0000);
|
|
BLANK();
|
|
DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
|
|
DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
|
|
DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
|
|
BLANK();
|
|
DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list));
|
|
DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
|
|
DEFINE(PROCINFO_MM_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mm_mmu_flags));
|
|
DEFINE(PROCINFO_IO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_io_mmu_flags));
|
|
BLANK();
|
|
#ifdef MULTI_DABORT
|
|
DEFINE(PROCESSOR_DABT_FUNC, offsetof(struct processor, _data_abort));
|
|
#endif
|
|
#ifdef MULTI_PABORT
|
|
DEFINE(PROCESSOR_PABT_FUNC, offsetof(struct processor, _prefetch_abort));
|
|
#endif
|
|
#ifdef MULTI_CPU
|
|
DEFINE(CPU_SLEEP_SIZE, offsetof(struct processor, suspend_size));
|
|
DEFINE(CPU_DO_SUSPEND, offsetof(struct processor, do_suspend));
|
|
DEFINE(CPU_DO_RESUME, offsetof(struct processor, do_resume));
|
|
#endif
|
|
#ifdef MULTI_CACHE
|
|
DEFINE(CACHE_FLUSH_KERN_ALL, offsetof(struct cpu_cache_fns, flush_kern_all));
|
|
#endif
|
|
#ifdef CONFIG_ARM_CPU_SUSPEND
|
|
DEFINE(SLEEP_SAVE_SP_SZ, sizeof(struct sleep_save_sp));
|
|
DEFINE(SLEEP_SAVE_SP_PHYS, offsetof(struct sleep_save_sp, save_ptr_stash_phys));
|
|
DEFINE(SLEEP_SAVE_SP_VIRT, offsetof(struct sleep_save_sp, save_ptr_stash));
|
|
#endif
|
|
BLANK();
|
|
DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL);
|
|
DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE);
|
|
DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE);
|
|
BLANK();
|
|
DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER);
|
|
DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE);
|
|
BLANK();
|
|
#ifdef CONFIG_VDSO
|
|
DEFINE(VDSO_DATA_SIZE, sizeof(union vdso_data_store));
|
|
#endif
|
|
BLANK();
|
|
#ifdef CONFIG_ARM_MPU
|
|
DEFINE(MPU_RNG_INFO_RNGS, offsetof(struct mpu_rgn_info, rgns));
|
|
DEFINE(MPU_RNG_INFO_USED, offsetof(struct mpu_rgn_info, used));
|
|
|
|
DEFINE(MPU_RNG_SIZE, sizeof(struct mpu_rgn));
|
|
DEFINE(MPU_RGN_DRBAR, offsetof(struct mpu_rgn, drbar));
|
|
DEFINE(MPU_RGN_DRSR, offsetof(struct mpu_rgn, drsr));
|
|
DEFINE(MPU_RGN_DRACR, offsetof(struct mpu_rgn, dracr));
|
|
DEFINE(MPU_RGN_PRBAR, offsetof(struct mpu_rgn, prbar));
|
|
DEFINE(MPU_RGN_PRLAR, offsetof(struct mpu_rgn, prlar));
|
|
#endif
|
|
DEFINE(KEXEC_START_ADDR, offsetof(struct kexec_relocate_data, kexec_start_address));
|
|
DEFINE(KEXEC_INDIR_PAGE, offsetof(struct kexec_relocate_data, kexec_indirection_page));
|
|
DEFINE(KEXEC_MACH_TYPE, offsetof(struct kexec_relocate_data, kexec_mach_type));
|
|
DEFINE(KEXEC_R2, offsetof(struct kexec_relocate_data, kexec_r2));
|
|
return 0;
|
|
}
|