x86/orc: Make it callthunk aware
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
This commit is contained in:
parent
f138918162
commit
396e0b8e09
@ -92,6 +92,7 @@ extern void callthunks_patch_builtin_calls(void);
|
|||||||
extern void callthunks_patch_module_calls(struct callthunk_sites *sites,
|
extern void callthunks_patch_module_calls(struct callthunk_sites *sites,
|
||||||
struct module *mod);
|
struct module *mod);
|
||||||
extern void *callthunks_translate_call_dest(void *dest);
|
extern void *callthunks_translate_call_dest(void *dest);
|
||||||
|
extern bool is_callthunk(void *addr);
|
||||||
#else
|
#else
|
||||||
static __always_inline void callthunks_patch_builtin_calls(void) {}
|
static __always_inline void callthunks_patch_builtin_calls(void) {}
|
||||||
static __always_inline void
|
static __always_inline void
|
||||||
@ -101,6 +102,10 @@ static __always_inline void *callthunks_translate_call_dest(void *dest)
|
|||||||
{
|
{
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
static __always_inline bool is_callthunk(void *addr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -293,6 +293,19 @@ void *callthunks_translate_call_dest(void *dest)
|
|||||||
return target ? : 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
|
#ifdef CONFIG_MODULES
|
||||||
void noinline callthunks_patch_module_calls(struct callthunk_sites *cs,
|
void noinline callthunks_patch_module_calls(struct callthunk_sites *cs,
|
||||||
struct module *mod)
|
struct module *mod)
|
||||||
|
@ -136,6 +136,21 @@ static struct orc_entry null_orc_entry = {
|
|||||||
.type = UNWIND_HINT_TYPE_CALL
|
.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 */
|
/* Fake frame pointer entry -- used as a fallback for generated code */
|
||||||
static struct orc_entry orc_fp_entry = {
|
static struct orc_entry orc_fp_entry = {
|
||||||
.type = UNWIND_HINT_TYPE_CALL,
|
.type = UNWIND_HINT_TYPE_CALL,
|
||||||
@ -189,7 +204,11 @@ static struct orc_entry *orc_find(unsigned long ip)
|
|||||||
if (orc)
|
if (orc)
|
||||||
return 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
|
#ifdef CONFIG_MODULES
|
||||||
|
Loading…
x
Reference in New Issue
Block a user