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:
Juergen Gross authored and Julien Grall committed 2021-01-23 11:30:32 +00:00
1 parent b470737229
commit c8d4b6304a
6 files changed
+40 -8

No files matched your search

+8
View File
@@ -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) )
+2
View File
@@ -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)
-2
View File
@@ -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
};
+2
View File
@@ -10,4 +10,6 @@
#define BUG_INSTR ".word " __stringify(BUG_OPCODE)
#define BUG_FN_REG r0
#endif /* __ARM_ARM32_BUG_H__ */
+2
View File
@@ -6,4 +6,6 @@
#define BUG_INSTR "brk " __stringify(BRK_BUG_FRAME_IMM)
#define BUG_FN_REG x0
#endif /* __ARM_ARM64_BUG_H__ */
+26 -6
View File
@@ -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__ */
/*
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.