Skip to content

Commit

Permalink
x86/orc: Make it callthunk aware
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Peter Zijlstra committed Oct 17, 2022
1 parent f138918 commit 396e0b8
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 1 deletion.
5 changes: 5 additions & 0 deletions arch/x86/include/asm/alternative.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
13 changes: 13 additions & 0 deletions arch/x86/kernel/callthunks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 20 additions & 1 deletion arch/x86/kernel/unwind_orc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 396e0b8

Please sign in to comment.