Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Kalesh Singh <kaleshsingh@google.com>
Reviewed-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
Reviewed-by: Mark 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.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Rutland and committed by
Catalin Marinas
bd8abd68 d1f684e4

+56 -46
+2 -4
arch/arm64/include/asm/stacktrace/common.h
··· 113 113 * pointer to a kernel address. 114 114 * 115 115 * @fp: the frame pointer to be updated to its kernel address. 116 - * @type: the stack type associated with frame pointer @fp 117 116 * 118 117 * Return: true if the VA can be translated, false otherwise. 119 118 * 120 119 * Upon success @fp is updated to the corresponding kernel virtual address. 121 120 */ 122 - typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp, 123 - enum stack_type type); 121 + typedef bool (*stack_trace_translate_fp_fn)(unsigned long *fp); 124 122 125 123 /** 126 124 * typedef on_accessible_stack_fn() - Check whether a stack range is on any of ··· 170 172 * If fp is not from the current address space perform the necessary 171 173 * translation before dereferencing it to get the next fp. 172 174 */ 173 - if (translate_fp && !translate_fp(&kern_fp, info.type)) 175 + if (translate_fp && !translate_fp(&kern_fp)) 174 176 return -EINVAL; 175 177 176 178 /*
+54 -42
arch/arm64/kvm/stacktrace.c
··· 21 21 22 22 #include <asm/stacktrace/nvhe.h> 23 23 24 - /* 25 - * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs 26 - * 27 - * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to 28 - * allow for guard pages below the stack. Consequently, the fixed offset address 29 - * translation macros won't work here. 30 - * 31 - * The kernel VA is calculated as an offset from the kernel VA of the hypervisor 32 - * stack base. 33 - * 34 - * Returns true on success and updates @addr to its corresponding kernel VA; 35 - * otherwise returns false. 36 - */ 37 - static bool kvm_nvhe_stack_kern_va(unsigned long *addr, 38 - enum stack_type type) 39 - { 40 - struct kvm_nvhe_stacktrace_info *stacktrace_info; 41 - unsigned long hyp_base, kern_base, hyp_offset; 42 - 43 - stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info); 44 - 45 - switch (type) { 46 - case STACK_TYPE_HYP: 47 - kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page); 48 - hyp_base = (unsigned long)stacktrace_info->stack_base; 49 - break; 50 - case STACK_TYPE_OVERFLOW: 51 - kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack); 52 - hyp_base = (unsigned long)stacktrace_info->overflow_stack_base; 53 - break; 54 - default: 55 - return false; 56 - } 57 - 58 - hyp_offset = *addr - hyp_base; 59 - 60 - *addr = kern_base + hyp_offset; 61 - 62 - return true; 63 - } 64 - 65 24 static struct stack_info stackinfo_get_overflow(void) 66 25 { 67 26 struct kvm_nvhe_stacktrace_info *stacktrace_info ··· 49 90 }; 50 91 } 51 92 93 + /* 94 + * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs 95 + * 96 + * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to 97 + * allow for guard pages below the stack. Consequently, the fixed offset address 98 + * translation macros won't work here. 99 + * 100 + * The kernel VA is calculated as an offset from the kernel VA of the hypervisor 101 + * stack base. 102 + * 103 + * Returns true on success and updates @addr to its corresponding kernel VA; 104 + * otherwise returns false. 105 + */ 106 + static bool kvm_nvhe_stack_kern_va(unsigned long *addr, unsigned long size) 107 + { 108 + struct kvm_nvhe_stacktrace_info *stacktrace_info; 109 + unsigned long hyp_base, kern_base, hyp_offset; 110 + struct stack_info stack; 111 + 112 + stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info); 113 + 114 + stack = stackinfo_get_hyp(); 115 + if (stackinfo_on_stack(&stack, *addr, size)) { 116 + kern_base = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_page); 117 + hyp_base = (unsigned long)stacktrace_info->stack_base; 118 + goto found; 119 + } 120 + 121 + stack = stackinfo_get_overflow(); 122 + if (stackinfo_on_stack(&stack, *addr, size)) { 123 + kern_base = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack); 124 + hyp_base = (unsigned long)stacktrace_info->overflow_stack_base; 125 + goto found; 126 + } 127 + 128 + return false; 129 + 130 + found: 131 + hyp_offset = *addr - hyp_base; 132 + 133 + *addr = kern_base + hyp_offset; 134 + 135 + return true; 136 + } 137 + 138 + /* 139 + * Convert a KVN nVHE HYP frame record address to a kernel VA 140 + */ 141 + static bool kvm_nvhe_stack_kern_record_va(unsigned long *addr) 142 + { 143 + return kvm_nvhe_stack_kern_va(addr, 16); 144 + } 145 + 52 146 static bool on_accessible_stack(const struct task_struct *tsk, 53 147 unsigned long sp, unsigned long size, 54 148 struct stack_info *info) ··· 127 115 static int unwind_next(struct unwind_state *state) 128 116 { 129 117 return unwind_next_frame_record(state, on_accessible_stack, 130 - kvm_nvhe_stack_kern_va); 118 + kvm_nvhe_stack_kern_record_va); 131 119 } 132 120 133 121 static void unwind(struct unwind_state *state,