diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h index 3c3bda34bb87..2f972441f572 100644 --- a/arch/arm64/include/asm/stacktrace/common.h +++ b/arch/arm64/include/asm/stacktrace/common.h @@ -113,14 +113,12 @@ static inline void unwind_init_common(struct unwind_state *state, * pointer to a 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. * * Upon success @fp is updated to the corresponding kernel virtual address. */ -typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp, - enum stack_type type); +typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp); /** * 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, * If fp is not from the current address space perform the necessary * 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; /* diff --git a/arch/arm64/kvm/stacktrace.c b/arch/arm64/kvm/stacktrace.c index 26927344a263..7658c5db47c1 100644 --- a/arch/arm64/kvm/stacktrace.c +++ b/arch/arm64/kvm/stacktrace.c @@ -21,47 +21,6 @@ #include -/* - * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs - * - * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to - * allow for guard pages below the stack. Consequently, the fixed offset address - * translation macros won't work here. - * - * The kernel VA is calculated as an offset from the kernel VA of the hypervisor - * stack base. - * - * Returns true on success and updates @addr to its corresponding kernel VA; - * otherwise returns false. - */ -static bool kvm_nvhe_stack_kern_va(unsigned long *addr, - enum stack_type type) -{ - struct kvm_nvhe_stacktrace_info *stacktrace_info; - unsigned long hyp_base, kern_base, hyp_offset; - - stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info); - - switch (type) { - case STACK_TYPE_HYP: - kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page); - hyp_base = (unsigned long)stacktrace_info->stack_base; - break; - case STACK_TYPE_OVERFLOW: - kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack); - hyp_base = (unsigned long)stacktrace_info->overflow_stack_base; - break; - default: - return false; - } - - hyp_offset = *addr - hyp_base; - - *addr = kern_base + hyp_offset; - - return true; -} - static struct stack_info stackinfo_get_overflow(void) { struct kvm_nvhe_stacktrace_info *stacktrace_info @@ -90,6 +49,59 @@ static struct stack_info stackinfo_get_hyp(void) }; } +/* + * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs + * + * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to + * allow for guard pages below the stack. Consequently, the fixed offset address + * translation macros won't work here. + * + * The kernel VA is calculated as an offset from the kernel VA of the hypervisor + * stack base. + * + * Returns true on success and updates @addr to its corresponding kernel VA; + * otherwise returns false. + */ +static bool kvm_nvhe_stack_kern_va(unsigned long *addr, unsigned long size) +{ + struct kvm_nvhe_stacktrace_info *stacktrace_info; + unsigned long hyp_base, kern_base, hyp_offset; + struct stack_info stack; + + stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info); + + stack = stackinfo_get_hyp(); + if (stackinfo_on_stack(&stack, *addr, size)) { + kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page); + hyp_base = (unsigned long)stacktrace_info->stack_base; + goto found; + } + + stack = stackinfo_get_overflow(); + if (stackinfo_on_stack(&stack, *addr, size)) { + kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack); + hyp_base = (unsigned long)stacktrace_info->overflow_stack_base; + goto found; + } + + return false; + +found: + hyp_offset = *addr - hyp_base; + + *addr = kern_base + hyp_offset; + + return true; +} + +/* + * Convert a KVN nVHE HYP frame record address to a kernel VA + */ +static bool kvm_nvhe_stack_kern_record_va(unsigned long *addr) +{ + return kvm_nvhe_stack_kern_va(addr, 16); +} + static bool on_accessible_stack(const struct task_struct *tsk, unsigned long sp, unsigned long size, struct stack_info *info) @@ -115,7 +127,7 @@ found: static int unwind_next(struct unwind_state *state) { 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,