Page MenuHomeFreeBSD

D59650.id186803.diff
No OneTemporary

D59650.id186803.diff

diff --git a/sys/arm/arm/exception.S b/sys/arm/arm/exception.S
--- a/sys/arm/arm/exception.S
+++ b/sys/arm/arm/exception.S
@@ -52,6 +52,7 @@
#include <machine/armreg.h>
#include <machine/asmacros.h>
#include <machine/trap.h>
+#include <machine/trap_cfi.h>
#include <sys/intr.h>
#ifdef KDTRACE_HOOKS
@@ -66,6 +67,15 @@
.text
.align 2
+.macro trap_split user, kernel, tmp
+ ldr \tmp, [sp, #TF_SPSR]
+ and \tmp, \tmp, #PSR_MODE
+ cmp \tmp, #PSR_USR32_MODE
+ beq \user
+ b \kernel
+ .cfi_endproc
+.endm
+
/*
* ASM macros for pushing and pulling trapframes from the stack
*
@@ -79,14 +89,27 @@
*/
#define PUSHFRAME \
sub sp, sp, #4; /* Align the stack */ \
+ .cfi_def_cfa sp, 0; \
str lr, [sp, #-4]!; /* Push the return address */ \
+ .cfi_def_cfa_offset 4; \
+ .cfi_offset 15, -4; \
sub sp, sp, #(4*17); /* Adjust the stack pointer */ \
+ .cfi_def_cfa_offset 72; \
stmia sp, {r0-r12}; /* Push the user mode registers */ \
+ .cfi_offset r0, -72; .cfi_offset r1, -68; \
+ .cfi_offset r2, -64; .cfi_offset r3, -60; \
+ .cfi_offset r4, -56; .cfi_offset r5, -52; \
+ .cfi_offset r6, -48; .cfi_offset r7, -44; \
+ .cfi_offset r8, -40; .cfi_offset r9, -36; \
+ .cfi_offset r10, -32; .cfi_offset r11, -28; \
+ .cfi_offset r12, -24; \
add r0, sp, #(4*13); /* Adjust the stack pointer */ \
stmia r0, {r13-r14}^; /* Push the user mode registers */ \
mov r0, r0; /* NOP for previous instruction */ \
mrs r0, spsr; /* Put the SPSR on the stack */ \
- str r0, [sp, #-4]!;
+ str r0, [sp, #-4]!; \
+ .cfi_def_cfa_offset 76; \
+ .cfi_offset CFI_CPSR, -76
/*
* PULLFRAME - macro to pull a trap frame from the stack in the current mode
@@ -95,13 +118,18 @@
#define PULLFRAME \
ldr r0, [sp], #4 ; /* Get the SPSR from stack */ \
+ .cfi_def_cfa_offset 72; \
msr spsr_fsxc, r0; \
clrex; \
ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
mov r0, r0; /* NOP for previous instruction */ \
add sp, sp, #(4*17); /* Adjust the stack pointer */ \
+ .cfi_def_cfa_offset 4; \
ldr lr, [sp], #4; /* Pull the return address */ \
- add sp, sp, #4 /* Align the stack */
+ .cfi_def_cfa_offset 0; \
+ .cfi_register 15, lr; \
+ add sp, sp, #4; /* Align the stack */ \
+ .cfi_def_cfa_offset -4
/*
* PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode
@@ -122,19 +150,33 @@
mov r2, sp; /* Save SVC sp */ \
bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \
sub sp, sp, #(4 * 17); /* Pad trapframe to keep alignment */ \
+ .cfi_def_cfa sp, 0; \
/* and for dtrace to emulate push/pop */ \
str r0, [sp, #-4]!; /* Push return address */ \
+ .cfi_def_cfa_offset 4; .cfi_offset 15, -4; \
str lr, [sp, #-4]!; /* Push SVC lr */ \
+ .cfi_def_cfa_offset 8; \
str r2, [sp, #-4]!; /* Push SVC sp */ \
+ .cfi_def_cfa_offset 12; \
msr spsr_fsxc, r3; /* Restore correct spsr */ \
ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \
sub sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ .cfi_def_cfa_offset 72; \
stmia sp, {r0-r12}; /* Push the user mode registers */ \
+ .cfi_offset r0, -72; .cfi_offset r1, -68; \
+ .cfi_offset r2, -64; .cfi_offset r3, -60; \
+ .cfi_offset r4, -56; .cfi_offset r5, -52; \
+ .cfi_offset r6, -48; .cfi_offset r7, -44; \
+ .cfi_offset r8, -40; .cfi_offset r9, -36; \
+ .cfi_offset r10, -32; .cfi_offset r11, -28; \
+ .cfi_offset r12, -24; \
add r0, sp, #(4*13); /* Adjust the stack pointer */ \
stmia r0, {r13-r14}^; /* Push the user mode registers */ \
mov r0, r0; /* NOP for previous instruction */ \
mrs r0, spsr; /* Put the SPSR on the stack */ \
- str r0, [sp, #-4]!
+ str r0, [sp, #-4]!; \
+ .cfi_def_cfa_offset 76; \
+ .cfi_offset CFI_CPSR, -76
/*
* PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack
@@ -145,11 +187,13 @@
#define PULLFRAMEFROMSVCANDEXIT \
ldr r0, [sp], #4; /* Get the SPSR from stack */ \
+ .cfi_def_cfa_offset 72; \
msr spsr_fsxc, r0; /* restore SPSR */ \
clrex; \
ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
mov r0, r0; /* NOP for previous instruction */ \
add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ .cfi_def_cfa_offset 12; \
ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */
/*
@@ -193,9 +237,30 @@
* right stack; just build a trapframe and call the handler.
*/
ASENTRY_NP(swi_entry)
+ .cfi_startproc
+ trap_cfi_entry empty
PUSHFRAME /* Build the trapframe on the */
+ trap_split swi_entry_user, swi_entry_kernel, r3
+
+ .type swi_entry_user, #function
+swi_entry_user:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full user
mov r0, sp /* scv32 stack, pass it to the */
bl _C_LABEL(swi_handler) /* swi handler. */
+ b swi_exit
+ .cfi_endproc
+
+ .type swi_entry_kernel, #function
+swi_entry_kernel:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full kernel
+ mov r0, sp
+ bl _C_LABEL(swi_handler)
+ b swi_exit_kernel
+ .cfi_endproc
/*
* The fork_trampoline() code in swtch.S aranges for the MI fork_exit()
* to return to swi_exit here, to return to userland. The net effect is
@@ -203,11 +268,35 @@
* the parent thread that created it.
*/
ASEENTRY_NP(swi_exit)
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full user
DO_AST /* Handle pending signals. */
PULLFRAME /* Deallocate trapframe. */
movs pc, lr /* Return to userland. */
STOP_UNWINDING /* Don't unwind into user mode. */
+ .cfi_endproc
EEND(swi_exit)
+
+ .type swi_exit_kernel, #function
+swi_exit_kernel:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full kernel
+ DO_AST
+ PULLFRAME
+ movs pc, lr
+ STOP_UNWINDING
+ .cfi_endproc
+
+ .globl swi_entry_kthread
+ .type swi_entry_kthread, #function
+swi_entry_kthread:
+ .cfi_startproc
+ trap_cfi_entry terminal
+ udf #0
+1: b 1b
+ .cfi_endproc
END(swi_entry)
/*
@@ -221,11 +310,25 @@
* signals and/or handle TDF_NEEDRESCHED first.
*/
ASENTRY_NP(exception_exit)
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full user
DO_AST /* Handle pending signals. */
PULLFRAMEFROMSVCANDEXIT /* Return. */
UNWINDSVCFRAME /* Special unwinding for exceptions. */
+ .cfi_endproc
END(exception_exit)
+ASENTRY_NP(exception_exit_kernel)
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full kernel
+ DO_AST
+ PULLFRAMEFROMSVCANDEXIT
+ UNWINDSVCFRAME
+ .cfi_endproc
+END(exception_exit_kernel)
+
/*
* Entry point for a Prefetch Abort exception.
*
@@ -234,12 +337,33 @@
* on exit (without transitioning back through the abort mode stack).
*/
ASENTRY_NP(prefetch_abort_entry)
+ .cfi_startproc
+ trap_cfi_entry empty
sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
- adr lr, exception_exit /* Return from handler via standard */
+ trap_split prefetch_abort_entry_user, prefetch_abort_entry_kernel, r3
+ .type prefetch_abort_entry_user, #function
+prefetch_abort_entry_user:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full user
+ adr lr, exception_exit
mov r0, sp /* exception exit routine. Pass the */
mov r1, #1 /* Type flag */
- b _C_LABEL(abort_handler)
+ bl _C_LABEL(abort_handler)
+ b exception_exit
+ .cfi_endproc
+ .type prefetch_abort_entry_kernel, #function
+prefetch_abort_entry_kernel:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full kernel
+ adr lr, exception_exit_kernel
+ mov r0, sp
+ mov r1, #1
+ bl _C_LABEL(abort_handler)
+ b exception_exit_kernel
+ .cfi_endproc
END(prefetch_abort_entry)
/*
@@ -250,12 +374,33 @@
* on exit (without transitioning back through the abort mode stack).
*/
ASENTRY_NP(data_abort_entry)
+ .cfi_startproc
+ trap_cfi_entry empty
sub lr, lr, #8 /* Adjust the lr. Transition to scv32 */
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
+ trap_split data_abort_entry_user, data_abort_entry_kernel, r3
+ .type data_abort_entry_user, #function
+data_abort_entry_user:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full user
adr lr, exception_exit /* Exception exit routine */
mov r0, sp /* Trapframe to the handler */
mov r1, #0 /* Type flag */
- b _C_LABEL(abort_handler)
+ bl _C_LABEL(abort_handler)
+ b exception_exit
+ .cfi_endproc
+ .type data_abort_entry_kernel, #function
+data_abort_entry_kernel:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full kernel
+ adr lr, exception_exit_kernel
+ mov r0, sp
+ mov r1, #0
+ bl _C_LABEL(abort_handler)
+ b exception_exit_kernel
+ .cfi_endproc
END(data_abort_entry)
/*
@@ -266,7 +411,15 @@
* on exit (without transitioning back through the undefined mode stack).
*/
ASENTRY_NP(undefined_entry)
+ .cfi_startproc
+ trap_cfi_entry empty
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
+ trap_split undefined_entry_user, undefined_entry_kernel, r3
+ .type undefined_entry_user, #function
+undefined_entry_user:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full user
mov r4, r0 /* R0 contains SPSR */
adr lr, exception_exit /* Return from handler via standard */
mov r0, sp /* exception exit routine. pass frame */
@@ -295,7 +448,36 @@
bx r3 /* call invop_jump_addr */
#endif
- b undefinedinstruction /* call stadnard handler */
+ bl undefinedinstruction /* call standard handler */
+ b exception_exit
+ .cfi_endproc
+ .type undefined_entry_kernel, #function
+undefined_entry_kernel:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full kernel
+ mov r4, r0
+ adr lr, exception_exit_kernel
+ mov r0, sp
+ ldr r2, [sp, #(TF_PC)]
+ tst r4, #(PSR_T)
+ subne r2, r2, #(THUMB_INSN_SIZE)
+ subeq r2, r2, #(INSN_SIZE)
+ str r2, [sp, #TF_PC]
+#ifdef KDTRACE_HOOKS
+ ldr r1, =_C_LABEL(dtrace_invop_jump_addr)
+ ldr r3, [r1]
+ cmp r3, #0
+ beq undefinedinstruction
+ ldr r4, [r2]
+ ldr r1, =FBT_BREAKPOINT
+ cmp r1, r4
+ bne undefinedinstruction
+ bx r3
+#endif
+ bl undefinedinstruction
+ b exception_exit_kernel
+ .cfi_endproc
END(undefined_entry)
/*
@@ -306,12 +488,33 @@
* on exit (without transitioning back through the IRQ mode stack).
*/
ASENTRY_NP(irq_entry)
+ .cfi_startproc
+ trap_cfi_entry empty
sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
+ trap_split irq_entry_user, irq_entry_kernel, r3
+ .type irq_entry_user, #function
+irq_entry_user:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full user
adr lr, exception_exit /* Return from handler via standard */
mov r0, sp /* exception exit routine. Pass the */
mov r1, #INTR_ROOT_IRQ /* trapframe and PIC root to the handler. */
- b _C_LABEL(intr_irq_handler)
+ bl _C_LABEL(intr_irq_handler)
+ b exception_exit
+ .cfi_endproc
+ .type irq_entry_kernel, #function
+irq_entry_kernel:
+ .cfi_startproc
+ trap_cfi_entry empty
+ trap_cfi_full kernel
+ adr lr, exception_exit_kernel
+ mov r0, sp
+ mov r1, #INTR_ROOT_IRQ
+ bl _C_LABEL(intr_irq_handler)
+ b exception_exit_kernel
+ .cfi_endproc
END(irq_entry)
/*
diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S
--- a/sys/arm/arm/swtch.S
+++ b/sys/arm/arm/swtch.S
@@ -114,3 +114,12 @@
b _C_LABEL(fork_exit) /* to userland via swi_exit code. */
END(fork_trampoline)
+ENTRY(fork_trampoline_kthread)
+ STOP_UNWINDING
+ mov fp, #0
+ mov r2, sp
+ mov r1, r5
+ mov r0, r4
+ ldr lr, =swi_entry_kthread
+ b _C_LABEL(fork_exit)
+END(fork_trampoline_kthread)
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -189,7 +189,10 @@
td->td_pcb->pcb_regs.sf_r4 = (register_t)fork_return;
td->td_pcb->pcb_regs.sf_r5 = (register_t)td;
- td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline;
+ if ((td->td_pflags & TDP_KTHREAD) != 0)
+ td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline_kthread;
+ else
+ td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline;
td->td_pcb->pcb_regs.sf_sp = (register_t)STACKALIGN(td->td_frame);
td->td_frame->tf_spsr &= ~PSR_C;
diff --git a/sys/arm/include/cpu.h b/sys/arm/include/cpu.h
--- a/sys/arm/include/cpu.h
+++ b/sys/arm/include/cpu.h
@@ -716,6 +716,7 @@
void arm_vector_init(vm_offset_t, int);
void fork_trampoline(void);
+void fork_trampoline_kthread(void);
void identify_arm_cpu(void);
void *initarm(struct arm_boot_params *);
diff --git a/sys/arm/include/frame.h b/sys/arm/include/frame.h
--- a/sys/arm/include/frame.h
+++ b/sys/arm/include/frame.h
@@ -56,6 +56,8 @@
/*
* Trap frame. Pushed onto the kernel stack on a trap (synchronous exception).
+ *
+ * NOTE: keep this structure in sync with the trap frame CFI information.
*/
struct trapframe {
diff --git a/sys/arm/include/trap_cfi.h b/sys/arm/include/trap_cfi.h
new file mode 100644
--- /dev/null
+++ b/sys/arm/include/trap_cfi.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2026 FreeBSD Foundation
+ *
+ * This software was developed by Minsoo Choo under sponsorship from the
+ * FreeBSD Foundation.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _MACHINE_TRAP_CFI_H_
+#define _MACHINE_TRAP_CFI_H_
+
+#include "assym.inc"
+
+ .cfi_sections .eh_frame
+
+#define CFI_TF_SIZE (TF_PC + 4)
+#define CFI_CPSR 16
+
+.macro trap_cfi_entry state=empty
+ .cfi_signal_frame
+ .cfi_return_column 15
+ .cfi_def_cfa sp, 0
+ .cfi_undefined 15
+.ifc \state,terminal
+ .cfi_def_cfa sp, CFI_TF_SIZE
+.endif
+.endm
+
+.macro trap_cfi_saved reg, off
+ .cfi_offset \reg, \off - CFI_TF_SIZE
+.endm
+
+.macro trap_cfi_full mode
+ .cfi_def_cfa sp, CFI_TF_SIZE
+ trap_cfi_saved CFI_CPSR, TF_SPSR
+ .irp n,0,1,2,3,4,5,6,7,8,9,10,11,12
+ trap_cfi_saved r\n, TF_R0 + \n * 4
+ .endr
+.ifc \mode,user
+ trap_cfi_saved sp, TF_R0 + 13 * 4
+ trap_cfi_saved lr, TF_R0 + 14 * 4
+.else
+ trap_cfi_saved sp, TF_R0 + 15 * 4
+ trap_cfi_saved lr, TF_R0 + 16 * 4
+.endif
+ trap_cfi_saved 15, TF_PC
+.endm
+
+#endif /* _MACHINE_TRAP_CFI_H_ */
diff --git a/sys/conf/ldscript.arm b/sys/conf/ldscript.arm
--- a/sys/conf/ldscript.arm
+++ b/sys/conf/ldscript.arm
@@ -31,6 +31,7 @@
*(.note.gnu.build-id)
PROVIDE (__build_id_end = .);
}
+ .eh_frame : { KEEP (*(.eh_frame)) }
.rel.text :
{ *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text :

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 24, 7:43 AM (20 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39329699
Default Alt Text
D59650.id186803.diff (14 KB)

Event Timeline