Skip to content

Commit 92b7624

Browse files
misalehMarc Zyngier
authored andcommitted
KVM: arm64: Dump instruction on hyp panic
Similar to the kernel panic, where the instruction code is printed, we can do the same for hypervisor panics. This patch does that only in case of “CONFIG_NVHE_EL2_DEBUG” or nvhe. The next patch adds support for pKVM. Also, remove the hardcoded argument dump_kernel_instr(). Signed-off-by: Mostafa Saleh <smostafa@google.com> Tested-by: Kunwu Chan <chentao@kylinos.cn> Reviewed-by: Kunwu Chan <chentao@kylinos.cn> Acked-by: Will Deacon <will@kernel.org> Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent 1b237f1 commit 92b7624

3 files changed

Lines changed: 15 additions & 6 deletions

File tree

arch/arm64/include/asm/traps.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ int kasan_brk_handler(struct pt_regs *regs, unsigned long esr);
3636
int ubsan_brk_handler(struct pt_regs *regs, unsigned long esr);
3737

3838
int early_brk64(unsigned long addr, unsigned long esr, struct pt_regs *regs);
39+
void dump_kernel_instr(unsigned long kaddr);
3940

4041
/*
4142
* Move regs->pc to next instruction and do necessary setup before it

arch/arm64/kernel/traps.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,27 +149,26 @@ pstate_check_t * const aarch32_opcode_cond_checks[16] = {
149149

150150
int show_unhandled_signals = 0;
151151

152-
static void dump_kernel_instr(const char *lvl, struct pt_regs *regs)
152+
void dump_kernel_instr(unsigned long kaddr)
153153
{
154-
unsigned long addr = instruction_pointer(regs);
155154
char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
156155
int i;
157156

158-
if (user_mode(regs))
157+
if (!is_ttbr1_addr(kaddr))
159158
return;
160159

161160
for (i = -4; i < 1; i++) {
162161
unsigned int val, bad;
163162

164-
bad = aarch64_insn_read(&((u32 *)addr)[i], &val);
163+
bad = aarch64_insn_read(&((u32 *)kaddr)[i], &val);
165164

166165
if (!bad)
167166
p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val);
168167
else
169168
p += sprintf(p, i == 0 ? "(????????) " : "???????? ");
170169
}
171170

172-
printk("%sCode: %s\n", lvl, str);
171+
printk(KERN_EMERG "Code: %s\n", str);
173172
}
174173

175174
#define S_SMP " SMP"
@@ -178,6 +177,7 @@ static int __die(const char *str, long err, struct pt_regs *regs)
178177
{
179178
static int die_counter;
180179
int ret;
180+
unsigned long addr = instruction_pointer(regs);
181181

182182
pr_emerg("Internal error: %s: %016lx [#%d] " S_SMP "\n",
183183
str, err, ++die_counter);
@@ -190,7 +190,10 @@ static int __die(const char *str, long err, struct pt_regs *regs)
190190
print_modules();
191191
show_regs(regs);
192192

193-
dump_kernel_instr(KERN_EMERG, regs);
193+
if (user_mode(regs))
194+
return ret;
195+
196+
dump_kernel_instr(addr);
194197

195198
return ret;
196199
}

arch/arm64/kvm/handle_exit.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,11 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
559559
/* Dump the nVHE hypervisor backtrace */
560560
kvm_nvhe_dump_backtrace(hyp_offset);
561561

562+
/* Dump the faulting instruction */
563+
if (!is_protected_kvm_enabled() ||
564+
IS_ENABLED(CONFIG_NVHE_EL2_DEBUG))
565+
dump_kernel_instr(panic_addr + kaslr_offset());
566+
562567
/*
563568
* Hyp has panicked and we're going to handle that by panicking the
564569
* kernel. The kernel offset will be revealed in the panic so we're

0 commit comments

Comments
 (0)