]> xenbits.xensource.com Git - xen.git/commitdiff
xen/arm: add support for run_in_exception_handler()
authorJuergen Gross <jgross@suse.com>
Sat, 16 Jan 2021 10:33:37 +0000 (11:33 +0100)
committerJulien Grall <jgrall@amazon.com>
Sat, 23 Jan 2021 11:30:32 +0000 (11:30 +0000)
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>
xen/arch/arm/traps.c
xen/arch/arm/xen.lds.S
xen/common/virtual_region.c
xen/include/asm-arm/arm32/bug.h
xen/include/asm-arm/arm64/bug.h
xen/include/asm-arm/bug.h

index 1af1bb9f1b2fb3d94edd2a7461eaf1b21ed02163..d0df33b2187f328064200791385398221ac46169 100644 (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) )
index 6342ac4eadf8e304d739495c7ad6e2d479a582cf..004b182acba68f4dc79296d4ca9987dd346806a0 100644 (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)
index 4fbc02e35abe85521ef393acfe633e489b0c594f..30b0b4ab9c85f10ed5a152c48ae198f0fc6ba31c 100644 (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
     };
 
index 3e66f35969fa2e3bb77616595dab6516d983106e..25cce151dca91d4fdfbf8b4ddd2d4d725a3b12c0 100644 (file)
@@ -10,4 +10,6 @@
 
 #define BUG_INSTR ".word " __stringify(BUG_OPCODE)
 
+#define BUG_FN_REG r0
+
 #endif /* __ARM_ARM32_BUG_H__ */
index 59f664d7deae7d3f716ef838f291d6d24080861a..5e11c0dfd5036f9b964498b13f4c357aa04d01ab 100644 (file)
@@ -6,4 +6,6 @@
 
 #define BUG_INSTR "brk " __stringify(BRK_BUG_FRAME_IMM)
 
+#define BUG_FN_REG x0
+
 #endif /* __ARM_ARM64_BUG_H__ */
index 36c803357c0866c691c9194e4852917fbfece480..f4088d0913208519949499aea47ecacb0a14368e 100644 (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__ */
 /*