mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/arm: add support for run_in_exception_handler()
Add support to run a function in an exception handler for Arm. Do it as on x86 via a bug_frame, but pass the function pointer via a register. This needs to be done that way because GCC will not allow to use "i" when PIE is enabled (Xen doesn't set the flag but instead rely on the default value from the compiler). Use the same BUGFRAME_* #defines as on x86 in order to make a future common header file more easily achievable. Signed-off-by: Juergen Gross <jgross@suse.com> [ julien: Add more details on the issue between "i" and -fpie ] Acked-by: Julien GralL <jgrall@amazon.com>
This commit is contained in:
1 parent
b470737229
commit
c8d4b6304a
6 files changed
+40
-8
No files matched your search
@@ -1236,6 +1236,14 @@ int do_bug_frame(const struct cpu_user_regs *regs, vaddr_t pc)
|
||||
if ( !bug )
|
||||
return -ENOENT;
|
||||
|
||||
if ( id == BUGFRAME_run_fn )
|
||||
{
|
||||
void (*fn)(const struct cpu_user_regs *) = (void *)regs->BUG_FN_REG;
|
||||
|
||||
fn(regs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WARN, BUG or ASSERT: decode the filename pointer and line number. */
|
||||
filename = bug_file(bug);
|
||||
if ( !is_kernel(filename) )
|
||||
|
||||
@@ -49,6 +49,8 @@ SECTIONS
|
||||
__stop_bug_frames_1 = .;
|
||||
*(.bug_frames.2)
|
||||
__stop_bug_frames_2 = .;
|
||||
*(.bug_frames.3)
|
||||
__stop_bug_frames_3 = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.data.rel.ro)
|
||||
|
||||
@@ -123,9 +123,7 @@ void __init setup_virtual_regions(const struct exception_table_entry *start,
|
||||
__stop_bug_frames_0,
|
||||
__stop_bug_frames_1,
|
||||
__stop_bug_frames_2,
|
||||
#ifdef CONFIG_X86
|
||||
__stop_bug_frames_3,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -10,4 +10,6 @@
|
||||
|
||||
#define BUG_INSTR ".word " __stringify(BUG_OPCODE)
|
||||
|
||||
#define BUG_FN_REG r0
|
||||
|
||||
#endif /* __ARM_ARM32_BUG_H__ */
|
||||
@@ -6,4 +6,6 @@
|
||||
|
||||
#define BUG_INSTR "brk " __stringify(BRK_BUG_FRAME_IMM)
|
||||
|
||||
#define BUG_FN_REG x0
|
||||
|
||||
#endif /* __ARM_ARM64_BUG_H__ */
|
||||
@@ -26,16 +26,17 @@ struct bug_frame {
|
||||
#define bug_line(b) ((b)->line)
|
||||
#define bug_msg(b) ((const char *)(b) + (b)->msg_disp)
|
||||
|
||||
#define BUGFRAME_warn 0
|
||||
#define BUGFRAME_bug 1
|
||||
#define BUGFRAME_assert 2
|
||||
#define BUGFRAME_run_fn 0
|
||||
#define BUGFRAME_warn 1
|
||||
#define BUGFRAME_bug 2
|
||||
#define BUGFRAME_assert 3
|
||||
|
||||
#define BUGFRAME_NR 3
|
||||
#define BUGFRAME_NR 4
|
||||
|
||||
/* Many versions of GCC doesn't support the asm %c parameter which would
|
||||
* be preferable to this unpleasantness. We use mergeable string
|
||||
* sections to avoid multiple copies of the string appearing in the
|
||||
* Xen image.
|
||||
* Xen image. BUGFRAME_run_fn needs to be handled separately.
|
||||
*/
|
||||
#define BUG_FRAME(type, line, file, has_msg, msg) do { \
|
||||
BUILD_BUG_ON((line) >> 16); \
|
||||
@@ -58,6 +59,24 @@ struct bug_frame {
|
||||
".popsection"); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* GCC will not allow to use "i" when PIE is enabled (Xen doesn't set the
|
||||
* flag but instead rely on the default value from the compiler). So the
|
||||
* easiest way to implement run_in_exception_handler() is to pass the to
|
||||
* be called function in a fixed register.
|
||||
*/
|
||||
#define run_in_exception_handler(fn) do { \
|
||||
asm ("mov " __stringify(BUG_FN_REG) ", %0\n" \
|
||||
"1:"BUG_INSTR"\n" \
|
||||
".pushsection .bug_frames." __stringify(BUGFRAME_run_fn) "," \
|
||||
" \"a\", %%progbits\n" \
|
||||
"2:\n" \
|
||||
".p2align 2\n" \
|
||||
".long (1b - 2b)\n" \
|
||||
".long 0, 0, 0\n" \
|
||||
".popsection" :: "r" (fn) : __stringify(BUG_FN_REG) ); \
|
||||
} while (0)
|
||||
|
||||
#define WARN() BUG_FRAME(BUGFRAME_warn, __LINE__, __FILE__, 0, "")
|
||||
|
||||
#define BUG() do { \
|
||||
@@ -73,7 +92,8 @@ struct bug_frame {
|
||||
extern const struct bug_frame __start_bug_frames[],
|
||||
__stop_bug_frames_0[],
|
||||
__stop_bug_frames_1[],
|
||||
__stop_bug_frames_2[];
|
||||
__stop_bug_frames_2[],
|
||||
__stop_bug_frames_3[];
|
||||
|
||||
#endif /* __ARM_BUG_H__ */
|
||||
/*
|
||||
|
||||