x86/orc: Make it callthunk aware
authorPeter Zijlstra <peterz@infradead.org>
Thu, 15 Sep 2022 11:11:33 +0000 (13:11 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 17 Oct 2022 14:41:17 +0000 (16:41 +0200)
Callthunks addresses on the stack would confuse the ORC unwinder. Handle
them correctly and tell ORC to proceed further down the stack.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220915111148.511637628@infradead.org
arch/x86/include/asm/alternative.h
arch/x86/kernel/callthunks.c
arch/x86/kernel/unwind_orc.c

index 07ac257..4b8cd25 100644 (file)
@@ -92,6 +92,7 @@ extern void callthunks_patch_builtin_calls(void);
 extern void callthunks_patch_module_calls(struct callthunk_sites *sites,
                                          struct module *mod);
 extern void *callthunks_translate_call_dest(void *dest);
+extern bool is_callthunk(void *addr);
 #else
 static __always_inline void callthunks_patch_builtin_calls(void) {}
 static __always_inline void
@@ -101,6 +102,10 @@ static __always_inline void *callthunks_translate_call_dest(void *dest)
 {
        return dest;
 }
+static __always_inline bool is_callthunk(void *addr)
+{
+       return false;
+}
 #endif
 
 #ifdef CONFIG_SMP
index 0710036..7f97881 100644 (file)
@@ -293,6 +293,19 @@ void *callthunks_translate_call_dest(void *dest)
        return target ? : dest;
 }
 
+bool is_callthunk(void *addr)
+{
+       unsigned int tmpl_size = SKL_TMPL_SIZE;
+       void *tmpl = skl_call_thunk_template;
+       unsigned long dest;
+
+       dest = roundup((unsigned long)addr, CONFIG_FUNCTION_ALIGNMENT);
+       if (!thunks_initialized || skip_addr((void *)dest))
+               return false;
+
+       return !bcmp((void *)(dest - tmpl_size), tmpl, tmpl_size);
+}
+
 #ifdef CONFIG_MODULES
 void noinline callthunks_patch_module_calls(struct callthunk_sites *cs,
                                            struct module *mod)
index 0ea57da..cfac2b5 100644 (file)
@@ -136,6 +136,21 @@ static struct orc_entry null_orc_entry = {
        .type = UNWIND_HINT_TYPE_CALL
 };
 
+#ifdef CONFIG_CALL_THUNKS
+static struct orc_entry *orc_callthunk_find(unsigned long ip)
+{
+       if (!is_callthunk((void *)ip))
+               return NULL;
+
+       return &null_orc_entry;
+}
+#else
+static struct orc_entry *orc_callthunk_find(unsigned long ip)
+{
+       return NULL;
+}
+#endif
+
 /* Fake frame pointer entry -- used as a fallback for generated code */
 static struct orc_entry orc_fp_entry = {
        .type           = UNWIND_HINT_TYPE_CALL,
@@ -189,7 +204,11 @@ static struct orc_entry *orc_find(unsigned long ip)
        if (orc)
                return orc;
 
-       return orc_ftrace_find(ip);
+       orc =  orc_ftrace_find(ip);
+       if (orc)
+               return orc;
+
+       return orc_callthunk_find(ip);
 }
 
 #ifdef CONFIG_MODULES