mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
parisc: Fix boot failure of 64-bit kernel
Commitc8921d72e3
("parisc: Fix and improve kernel stack unwinding") broke booting of 64-bit kernels. On 64-bit kernels function pointers are actually function descriptors which require dereferencing. In this patch we instead declare functions in assembly code which are referenced from C-code as external data pointers with the ENTRY() macro and thus can use a simple external reference to the functions. Signed-off-by: Helge Deller <deller@gmx.de> Fixes:c8921d72e3
("parisc: Fix and improve kernel stack unwinding")
This commit is contained in:
@@ -22,15 +22,6 @@
|
|||||||
name: ASM_NL\
|
name: ASM_NL\
|
||||||
.export name
|
.export name
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
|
||||||
#define ENDPROC(name) \
|
|
||||||
END(name)
|
|
||||||
#else
|
|
||||||
#define ENDPROC(name) \
|
|
||||||
.type name, @function !\
|
|
||||||
END(name)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ENTRY_CFI(name, ...) \
|
#define ENTRY_CFI(name, ...) \
|
||||||
ENTRY(name) ASM_NL\
|
ENTRY(name) ASM_NL\
|
||||||
.proc ASM_NL\
|
.proc ASM_NL\
|
||||||
|
@@ -777,7 +777,7 @@ END(fault_vector_11)
|
|||||||
* copy_thread moved args into task save area.
|
* copy_thread moved args into task save area.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ENTRY_CFI(ret_from_kernel_thread)
|
ENTRY(ret_from_kernel_thread)
|
||||||
/* Call schedule_tail first though */
|
/* Call schedule_tail first though */
|
||||||
BL schedule_tail, %r2
|
BL schedule_tail, %r2
|
||||||
nop
|
nop
|
||||||
@@ -792,7 +792,7 @@ ENTRY_CFI(ret_from_kernel_thread)
|
|||||||
copy %r31, %r2
|
copy %r31, %r2
|
||||||
b finish_child_return
|
b finish_child_return
|
||||||
nop
|
nop
|
||||||
ENDPROC_CFI(ret_from_kernel_thread)
|
END(ret_from_kernel_thread)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -816,9 +816,8 @@ ENTRY_CFI(_switch_to)
|
|||||||
LDREG TASK_THREAD_INFO(%r25), %r25
|
LDREG TASK_THREAD_INFO(%r25), %r25
|
||||||
bv %r0(%r2)
|
bv %r0(%r2)
|
||||||
mtctl %r25,%cr30
|
mtctl %r25,%cr30
|
||||||
ENDPROC_CFI(_switch_to)
|
|
||||||
|
|
||||||
ENTRY_CFI(_switch_to_ret)
|
ENTRY(_switch_to_ret)
|
||||||
mtctl %r0, %cr0 /* Needed for single stepping */
|
mtctl %r0, %cr0 /* Needed for single stepping */
|
||||||
callee_rest
|
callee_rest
|
||||||
callee_rest_float
|
callee_rest_float
|
||||||
@@ -826,7 +825,7 @@ ENTRY_CFI(_switch_to_ret)
|
|||||||
LDREG -RP_OFFSET(%r30), %r2
|
LDREG -RP_OFFSET(%r30), %r2
|
||||||
bv %r0(%r2)
|
bv %r0(%r2)
|
||||||
copy %r26, %r28
|
copy %r26, %r28
|
||||||
ENDPROC_CFI(_switch_to_ret)
|
ENDPROC_CFI(_switch_to)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common rfi return path for interruptions, kernel execve, and
|
* Common rfi return path for interruptions, kernel execve, and
|
||||||
@@ -887,14 +886,12 @@ ENTRY_CFI(syscall_exit_rfi)
|
|||||||
STREG %r19,PT_SR5(%r16)
|
STREG %r19,PT_SR5(%r16)
|
||||||
STREG %r19,PT_SR6(%r16)
|
STREG %r19,PT_SR6(%r16)
|
||||||
STREG %r19,PT_SR7(%r16)
|
STREG %r19,PT_SR7(%r16)
|
||||||
ENDPROC_CFI(syscall_exit_rfi)
|
|
||||||
|
|
||||||
ENTRY_CFI(intr_return)
|
ENTRY(intr_return)
|
||||||
/* check for reschedule */
|
/* check for reschedule */
|
||||||
mfctl %cr30,%r1
|
mfctl %cr30,%r1
|
||||||
LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
|
LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
|
||||||
bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
|
bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
|
||||||
ENDPROC_CFI(intr_return)
|
|
||||||
|
|
||||||
.import do_notify_resume,code
|
.import do_notify_resume,code
|
||||||
intr_check_sig:
|
intr_check_sig:
|
||||||
@@ -1050,6 +1047,7 @@ intr_extint:
|
|||||||
|
|
||||||
b do_cpu_irq_mask
|
b do_cpu_irq_mask
|
||||||
ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */
|
ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */
|
||||||
|
ENDPROC_CFI(syscall_exit_rfi)
|
||||||
|
|
||||||
|
|
||||||
/* Generic interruptions (illegal insn, unaligned, page fault, etc) */
|
/* Generic interruptions (illegal insn, unaligned, page fault, etc) */
|
||||||
@@ -1751,7 +1749,7 @@ fork_like fork
|
|||||||
fork_like vfork
|
fork_like vfork
|
||||||
|
|
||||||
/* Set the return value for the child */
|
/* Set the return value for the child */
|
||||||
ENTRY_CFI(child_return)
|
ENTRY(child_return)
|
||||||
BL schedule_tail, %r2
|
BL schedule_tail, %r2
|
||||||
nop
|
nop
|
||||||
finish_child_return:
|
finish_child_return:
|
||||||
@@ -1763,7 +1761,7 @@ finish_child_return:
|
|||||||
reg_restore %r1
|
reg_restore %r1
|
||||||
b syscall_exit
|
b syscall_exit
|
||||||
copy %r0,%r28
|
copy %r0,%r28
|
||||||
ENDPROC_CFI(child_return)
|
END(child_return)
|
||||||
|
|
||||||
ENTRY_CFI(sys_rt_sigreturn_wrapper)
|
ENTRY_CFI(sys_rt_sigreturn_wrapper)
|
||||||
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
|
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
|
||||||
@@ -1795,7 +1793,7 @@ ENTRY_CFI(sys_rt_sigreturn_wrapper)
|
|||||||
LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
|
LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
|
||||||
ENDPROC_CFI(sys_rt_sigreturn_wrapper)
|
ENDPROC_CFI(sys_rt_sigreturn_wrapper)
|
||||||
|
|
||||||
ENTRY_CFI(syscall_exit)
|
ENTRY(syscall_exit)
|
||||||
/* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
|
/* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
|
||||||
* via syscall_exit_rfi if the signal was received while the process
|
* via syscall_exit_rfi if the signal was received while the process
|
||||||
* was running.
|
* was running.
|
||||||
@@ -1994,15 +1992,13 @@ syscall_do_resched:
|
|||||||
#else
|
#else
|
||||||
nop
|
nop
|
||||||
#endif
|
#endif
|
||||||
ENDPROC_CFI(syscall_exit)
|
END(syscall_exit)
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_FUNCTION_TRACER
|
#ifdef CONFIG_FUNCTION_TRACER
|
||||||
|
|
||||||
.import ftrace_function_trampoline,code
|
.import ftrace_function_trampoline,code
|
||||||
.align L1_CACHE_BYTES
|
.align L1_CACHE_BYTES
|
||||||
.globl mcount
|
|
||||||
.type mcount, @function
|
|
||||||
ENTRY_CFI(mcount, caller)
|
ENTRY_CFI(mcount, caller)
|
||||||
_mcount:
|
_mcount:
|
||||||
.export _mcount,data
|
.export _mcount,data
|
||||||
@@ -2031,8 +2027,6 @@ ENDPROC_CFI(mcount)
|
|||||||
|
|
||||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||||
.align 8
|
.align 8
|
||||||
.globl return_to_handler
|
|
||||||
.type return_to_handler, @function
|
|
||||||
ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE)
|
ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE)
|
||||||
.export parisc_return_to_handler,data
|
.export parisc_return_to_handler,data
|
||||||
parisc_return_to_handler:
|
parisc_return_to_handler:
|
||||||
@@ -2082,6 +2076,7 @@ ENDPROC_CFI(return_to_handler)
|
|||||||
/* void call_on_stack(unsigned long param1, void *func,
|
/* void call_on_stack(unsigned long param1, void *func,
|
||||||
unsigned long new_stack) */
|
unsigned long new_stack) */
|
||||||
ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP)
|
ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP)
|
||||||
|
ENTRY(_call_on_stack)
|
||||||
copy %sp, %r1
|
copy %sp, %r1
|
||||||
|
|
||||||
/* Regarding the HPPA calling conventions for function pointers,
|
/* Regarding the HPPA calling conventions for function pointers,
|
||||||
|
@@ -209,6 +209,8 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
|
|||||||
* We have to use void * instead of a function pointer, because
|
* We have to use void * instead of a function pointer, because
|
||||||
* function pointers aren't a pointer to the function on 64-bit.
|
* function pointers aren't a pointer to the function on 64-bit.
|
||||||
* Make them const so the compiler knows they live in .text
|
* Make them const so the compiler knows they live in .text
|
||||||
|
* Note: We could use dereference_kernel_function_descriptor()
|
||||||
|
* instead but we want to keep it simple here.
|
||||||
*/
|
*/
|
||||||
extern void * const handle_interruption;
|
extern void * const handle_interruption;
|
||||||
extern void * const ret_from_kernel_thread;
|
extern void * const ret_from_kernel_thread;
|
||||||
@@ -216,7 +218,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
|
|||||||
extern void * const intr_return;
|
extern void * const intr_return;
|
||||||
extern void * const _switch_to_ret;
|
extern void * const _switch_to_ret;
|
||||||
#ifdef CONFIG_IRQSTACKS
|
#ifdef CONFIG_IRQSTACKS
|
||||||
extern void * const call_on_stack;
|
extern void * const _call_on_stack;
|
||||||
#endif /* CONFIG_IRQSTACKS */
|
#endif /* CONFIG_IRQSTACKS */
|
||||||
|
|
||||||
if (pc == (unsigned long) &handle_interruption) {
|
if (pc == (unsigned long) &handle_interruption) {
|
||||||
@@ -251,7 +253,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IRQSTACKS
|
#ifdef CONFIG_IRQSTACKS
|
||||||
if (pc == (unsigned long) &call_on_stack) {
|
if (pc == (unsigned long) &_call_on_stack) {
|
||||||
info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
|
info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
|
||||||
info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
|
info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
|
||||||
return 1;
|
return 1;
|
||||||
|
Reference in New Issue
Block a user