Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F173065286
D59650.id186803.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D59650.id186803.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D59650: trap_cfi(9): introduce arm implementation
Attached
Detach File
Event Timeline
Log In to Comment