Commit bd8abd68 authored by Mark Rutland's avatar Mark Rutland Committed by Catalin Marinas

arm64: stacktrace: remove stack type from fp translator

In subsequent patches we'll remove the stack_type enum, and move the FP
translation logic out of the raw FP unwind code.

In preparation for doing so, this patch removes the type parameter from
the FP translation callback, and modifies kvm_nvhe_stack_kern_va() to
determine the relevant stack directly.

So that kvm_nvhe_stack_kern_va() can use the stackinfo_*() helpers,
these are moved earlier in the file, but are not modified in any way.

There should be no functional change as a result of this patch.
Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Reviewed-by: default avatarKalesh Singh <kaleshsingh@google.com>
Reviewed-by: default avatarMadhavan T. Venkataraman <madvenka@linux.microsoft.com>
Reviewed-by: default avatarMark Brown <broonie@kernel.org>
Cc: Fuad Tabba <tabba@google.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20220901130646.1316937-8-mark.rutland@arm.comSigned-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent d1f684e4
...@@ -113,14 +113,12 @@ static inline void unwind_init_common(struct unwind_state *state, ...@@ -113,14 +113,12 @@ static inline void unwind_init_common(struct unwind_state *state,
* pointer to a kernel address. * pointer to a kernel address.
* *
* @fp: the frame pointer to be updated to its kernel address. * @fp: the frame pointer to be updated to its kernel address.
* @type: the stack type associated with frame pointer @fp
* *
* Return: true if the VA can be translated, false otherwise. * Return: true if the VA can be translated, false otherwise.
* *
* Upon success @fp is updated to the corresponding kernel virtual address. * Upon success @fp is updated to the corresponding kernel virtual address.
*/ */
typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp, typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp);
enum stack_type type);
/** /**
* typedef on_accessible_stack_fn() - Check whether a stack range is on any of * typedef on_accessible_stack_fn() - Check whether a stack range is on any of
...@@ -172,7 +170,7 @@ unwind_next_frame_record(struct unwind_state *state, ...@@ -172,7 +170,7 @@ unwind_next_frame_record(struct unwind_state *state,
* If fp is not from the current address space perform the necessary * If fp is not from the current address space perform the necessary
* translation before dereferencing it to get the next fp. * translation before dereferencing it to get the next fp.
*/ */
if (translate_fp && !translate_fp(&kern_fp, info.type)) if (translate_fp && !translate_fp(&kern_fp))
return -EINVAL; return -EINVAL;
/* /*
......
...@@ -21,6 +21,34 @@ ...@@ -21,6 +21,34 @@
#include <asm/stacktrace/nvhe.h> #include <asm/stacktrace/nvhe.h>
static struct stack_info stackinfo_get_overflow(void)
{
struct kvm_nvhe_stacktrace_info *stacktrace_info
= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
unsigned long high = low + OVERFLOW_STACK_SIZE;
return (struct stack_info) {
.low = low,
.high = high,
.type = STACK_TYPE_OVERFLOW,
};
}
static struct stack_info stackinfo_get_hyp(void)
{
struct kvm_nvhe_stacktrace_info *stacktrace_info
= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
unsigned long low = (unsigned long)stacktrace_info->stack_base;
unsigned long high = low + PAGE_SIZE;
return (struct stack_info) {
.low = low,
.high = high,
.type = STACK_TYPE_HYP,
};
}
/* /*
* kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
* *
...@@ -34,27 +62,31 @@ ...@@ -34,27 +62,31 @@
* Returns true on success and updates @addr to its corresponding kernel VA; * Returns true on success and updates @addr to its corresponding kernel VA;
* otherwise returns false. * otherwise returns false.
*/ */
static bool kvm_nvhe_stack_kern_va(unsigned long *addr, static bool kvm_nvhe_stack_kern_va(unsigned long *addr, unsigned long size)
enum stack_type type)
{ {
struct kvm_nvhe_stacktrace_info *stacktrace_info; struct kvm_nvhe_stacktrace_info *stacktrace_info;
unsigned long hyp_base, kern_base, hyp_offset; unsigned long hyp_base, kern_base, hyp_offset;
struct stack_info stack;
stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info); stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
switch (type) { stack = stackinfo_get_hyp();
case STACK_TYPE_HYP: if (stackinfo_on_stack(&stack, *addr, size)) {
kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page); kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page);
hyp_base = (unsigned long)stacktrace_info->stack_base; hyp_base = (unsigned long)stacktrace_info->stack_base;
break; goto found;
case STACK_TYPE_OVERFLOW: }
stack = stackinfo_get_overflow();
if (stackinfo_on_stack(&stack, *addr, size)) {
kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack); kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
hyp_base = (unsigned long)stacktrace_info->overflow_stack_base; hyp_base = (unsigned long)stacktrace_info->overflow_stack_base;
break; goto found;
default:
return false;
} }
return false;
found:
hyp_offset = *addr - hyp_base; hyp_offset = *addr - hyp_base;
*addr = kern_base + hyp_offset; *addr = kern_base + hyp_offset;
...@@ -62,32 +94,12 @@ static bool kvm_nvhe_stack_kern_va(unsigned long *addr, ...@@ -62,32 +94,12 @@ static bool kvm_nvhe_stack_kern_va(unsigned long *addr,
return true; return true;
} }
static struct stack_info stackinfo_get_overflow(void) /*
{ * Convert a KVN nVHE HYP frame record address to a kernel VA
struct kvm_nvhe_stacktrace_info *stacktrace_info */
= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info); static bool kvm_nvhe_stack_kern_record_va(unsigned long *addr)
unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
unsigned long high = low + OVERFLOW_STACK_SIZE;
return (struct stack_info) {
.low = low,
.high = high,
.type = STACK_TYPE_OVERFLOW,
};
}
static struct stack_info stackinfo_get_hyp(void)
{ {
struct kvm_nvhe_stacktrace_info *stacktrace_info return kvm_nvhe_stack_kern_va(addr, 16);
= this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
unsigned long low = (unsigned long)stacktrace_info->stack_base;
unsigned long high = low + PAGE_SIZE;
return (struct stack_info) {
.low = low,
.high = high,
.type = STACK_TYPE_HYP,
};
} }
static bool on_accessible_stack(const struct task_struct *tsk, static bool on_accessible_stack(const struct task_struct *tsk,
...@@ -115,7 +127,7 @@ static bool on_accessible_stack(const struct task_struct *tsk, ...@@ -115,7 +127,7 @@ static bool on_accessible_stack(const struct task_struct *tsk,
static int unwind_next(struct unwind_state *state) static int unwind_next(struct unwind_state *state)
{ {
return unwind_next_frame_record(state, on_accessible_stack, return unwind_next_frame_record(state, on_accessible_stack,
kvm_nvhe_stack_kern_va); kvm_nvhe_stack_kern_record_va);
} }
static void unwind(struct unwind_state *state, static void unwind(struct unwind_state *state,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment