|
Takashi Iwai |
e8a81f |
From 86ddc7397906772f877e9f32defa819b4edc77c0 Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
e8a81f |
From: Will Deacon <will@kernel.org>
|
|
Takashi Iwai |
e8a81f |
Date: Fri, 13 Aug 2021 14:03:36 +0100
|
|
Takashi Iwai |
e8a81f |
Subject: [PATCH] KVM: arm64: Make hyp_panic() more robust when protected mode is enabled
|
|
Takashi Iwai |
e8a81f |
Git-commit: ccac96977243d7916053550f62e6489760ad0adc
|
|
Takashi Iwai |
e8a81f |
Patch-mainline: v5.15-rc1
|
|
Takashi Iwai |
e8a81f |
References: stable-5.14.7
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
[ Upstream commit ccac96977243d7916053550f62e6489760ad0adc ]
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
When protected mode is enabled, the host is unable to access most parts
|
|
Takashi Iwai |
e8a81f |
of the EL2 hypervisor image, including 'hyp_physvirt_offset' and the
|
|
Takashi Iwai |
e8a81f |
contents of the hypervisor's '.rodata.str' section. Unfortunately,
|
|
Takashi Iwai |
e8a81f |
nvhe_hyp_panic_handler() tries to read from both of these locations when
|
|
Takashi Iwai |
e8a81f |
handling a BUG() triggered at EL2; the former for converting the ELR to
|
|
Takashi Iwai |
e8a81f |
a physical address and the latter for displaying the name of the source
|
|
Takashi Iwai |
e8a81f |
file where the BUG() occurred.
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
Hack the EL2 panic asm to pass both physical and virtual ELR values to
|
|
Takashi Iwai |
e8a81f |
the host and utilise the newly introduced CONFIG_NVHE_EL2_DEBUG so that
|
|
Takashi Iwai |
e8a81f |
we disable stage-2 protection for the host before returning to the EL1
|
|
Takashi Iwai |
e8a81f |
panic handler. If the debug option is not enabled, display the address
|
|
Takashi Iwai |
e8a81f |
instead of the source file:line information.
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
Cc: Andrew Scull <ascull@google.com>
|
|
Takashi Iwai |
e8a81f |
Cc: Quentin Perret <qperret@google.com>
|
|
Takashi Iwai |
e8a81f |
Signed-off-by: Will Deacon <will@kernel.org>
|
|
Takashi Iwai |
e8a81f |
Signed-off-by: Marc Zyngier <maz@kernel.org>
|
|
Takashi Iwai |
e8a81f |
Link: https://lore.kernel.org/r/20210813130336.8139-1-will@kernel.org
|
|
Takashi Iwai |
e8a81f |
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
|
Takashi Iwai |
e8a81f |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
---
|
|
Takashi Iwai |
e8a81f |
arch/arm64/kvm/handle_exit.c | 23 ++++++++++++++---------
|
|
Takashi Iwai |
e8a81f |
arch/arm64/kvm/hyp/nvhe/host.S | 21 +++++++++++++++++----
|
|
Takashi Iwai |
e8a81f |
2 files changed, 31 insertions(+), 13 deletions(-)
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
|
|
Takashi Iwai |
e8a81f |
index 6f48336b1d86..04ebab299aa4 100644
|
|
Takashi Iwai |
e8a81f |
--- a/arch/arm64/kvm/handle_exit.c
|
|
Takashi Iwai |
e8a81f |
+++ b/arch/arm64/kvm/handle_exit.c
|
|
Takashi Iwai |
e8a81f |
@@ -292,11 +292,12 @@ void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index)
|
|
Takashi Iwai |
e8a81f |
kvm_handle_guest_serror(vcpu, kvm_vcpu_get_esr(vcpu));
|
|
Takashi Iwai |
e8a81f |
}
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
-void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr,
|
|
Takashi Iwai |
e8a81f |
+void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
|
|
Takashi Iwai |
e8a81f |
+ u64 elr_virt, u64 elr_phys,
|
|
Takashi Iwai |
e8a81f |
u64 par, uintptr_t vcpu,
|
|
Takashi Iwai |
e8a81f |
u64 far, u64 hpfar) {
|
|
Takashi Iwai |
e8a81f |
- u64 elr_in_kimg = __phys_to_kimg(__hyp_pa(elr));
|
|
Takashi Iwai |
e8a81f |
- u64 hyp_offset = elr_in_kimg - kaslr_offset() - elr;
|
|
Takashi Iwai |
e8a81f |
+ u64 elr_in_kimg = __phys_to_kimg(elr_phys);
|
|
Takashi Iwai |
e8a81f |
+ u64 hyp_offset = elr_in_kimg - kaslr_offset() - elr_virt;
|
|
Takashi Iwai |
e8a81f |
u64 mode = spsr & PSR_MODE_MASK;
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
/*
|
|
Takashi Iwai |
e8a81f |
@@ -309,20 +310,24 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr,
|
|
Takashi Iwai |
e8a81f |
kvm_err("Invalid host exception to nVHE hyp!\n");
|
|
Takashi Iwai |
e8a81f |
} else if (ESR_ELx_EC(esr) == ESR_ELx_EC_BRK64 &&
|
|
Takashi Iwai |
e8a81f |
(esr & ESR_ELx_BRK64_ISS_COMMENT_MASK) == BUG_BRK_IMM) {
|
|
Takashi Iwai |
e8a81f |
- struct bug_entry *bug = find_bug(elr_in_kimg);
|
|
Takashi Iwai |
e8a81f |
const char *file = NULL;
|
|
Takashi Iwai |
e8a81f |
unsigned int line = 0;
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
/* All hyp bugs, including warnings, are treated as fatal. */
|
|
Takashi Iwai |
e8a81f |
- if (bug)
|
|
Takashi Iwai |
e8a81f |
- bug_get_file_line(bug, &file, &line);
|
|
Takashi Iwai |
e8a81f |
+ if (!is_protected_kvm_enabled() ||
|
|
Takashi Iwai |
e8a81f |
+ IS_ENABLED(CONFIG_NVHE_EL2_DEBUG)) {
|
|
Takashi Iwai |
e8a81f |
+ struct bug_entry *bug = find_bug(elr_in_kimg);
|
|
Takashi Iwai |
e8a81f |
+
|
|
Takashi Iwai |
e8a81f |
+ if (bug)
|
|
Takashi Iwai |
e8a81f |
+ bug_get_file_line(bug, &file, &line);
|
|
Takashi Iwai |
e8a81f |
+ }
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
if (file)
|
|
Takashi Iwai |
e8a81f |
kvm_err("nVHE hyp BUG at: %s:%u!\n", file, line);
|
|
Takashi Iwai |
e8a81f |
else
|
|
Takashi Iwai |
e8a81f |
- kvm_err("nVHE hyp BUG at: %016llx!\n", elr + hyp_offset);
|
|
Takashi Iwai |
e8a81f |
+ kvm_err("nVHE hyp BUG at: %016llx!\n", elr_virt + hyp_offset);
|
|
Takashi Iwai |
e8a81f |
} else {
|
|
Takashi Iwai |
e8a81f |
- kvm_err("nVHE hyp panic at: %016llx!\n", elr + hyp_offset);
|
|
Takashi Iwai |
e8a81f |
+ kvm_err("nVHE hyp panic at: %016llx!\n", elr_virt + hyp_offset);
|
|
Takashi Iwai |
e8a81f |
}
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
/*
|
|
Takashi Iwai |
e8a81f |
@@ -334,5 +339,5 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr,
|
|
Takashi Iwai |
e8a81f |
kvm_err("Hyp Offset: 0x%llx\n", hyp_offset);
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
panic("HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%016lx\n",
|
|
Takashi Iwai |
e8a81f |
- spsr, elr, esr, far, hpfar, par, vcpu);
|
|
Takashi Iwai |
e8a81f |
+ spsr, elr_virt, esr, far, hpfar, par, vcpu);
|
|
Takashi Iwai |
e8a81f |
}
|
|
Takashi Iwai |
e8a81f |
diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S
|
|
Takashi Iwai |
e8a81f |
index 2b23400e0fb3..4b652ffb591d 100644
|
|
Takashi Iwai |
e8a81f |
--- a/arch/arm64/kvm/hyp/nvhe/host.S
|
|
Takashi Iwai |
e8a81f |
+++ b/arch/arm64/kvm/hyp/nvhe/host.S
|
|
Takashi Iwai |
e8a81f |
@@ -7,6 +7,7 @@
|
|
Takashi Iwai |
e8a81f |
#include <linux/linkage.h>
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
#include <asm/assembler.h>
|
|
Takashi Iwai |
e8a81f |
+#include <asm/kvm_arm.h>
|
|
Takashi Iwai |
e8a81f |
#include <asm/kvm_asm.h>
|
|
Takashi Iwai |
e8a81f |
#include <asm/kvm_mmu.h>
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
@@ -85,12 +86,24 @@ SYM_FUNC_START(__hyp_do_panic)
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
mov x29, x0
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
+#ifdef CONFIG_NVHE_EL2_DEBUG
|
|
Takashi Iwai |
e8a81f |
+ /* Ensure host stage-2 is disabled */
|
|
Takashi Iwai |
e8a81f |
+ mrs x0, hcr_el2
|
|
Takashi Iwai |
e8a81f |
+ bic x0, x0, #HCR_VM
|
|
Takashi Iwai |
e8a81f |
+ msr hcr_el2, x0
|
|
Takashi Iwai |
e8a81f |
+ isb
|
|
Takashi Iwai |
e8a81f |
+ tlbi vmalls12e1
|
|
Takashi Iwai |
e8a81f |
+ dsb nsh
|
|
Takashi Iwai |
e8a81f |
+#endif
|
|
Takashi Iwai |
e8a81f |
+
|
|
Takashi Iwai |
e8a81f |
/* Load the panic arguments into x0-7 */
|
|
Takashi Iwai |
e8a81f |
mrs x0, esr_el2
|
|
Takashi Iwai |
e8a81f |
- get_vcpu_ptr x4, x5
|
|
Takashi Iwai |
e8a81f |
- mrs x5, far_el2
|
|
Takashi Iwai |
e8a81f |
- mrs x6, hpfar_el2
|
|
Takashi Iwai |
e8a81f |
- mov x7, xzr // Unused argument
|
|
Takashi Iwai |
e8a81f |
+ mov x4, x3
|
|
Takashi Iwai |
e8a81f |
+ mov x3, x2
|
|
Takashi Iwai |
e8a81f |
+ hyp_pa x3, x6
|
|
Takashi Iwai |
e8a81f |
+ get_vcpu_ptr x5, x6
|
|
Takashi Iwai |
e8a81f |
+ mrs x6, far_el2
|
|
Takashi Iwai |
e8a81f |
+ mrs x7, hpfar_el2
|
|
Takashi Iwai |
e8a81f |
|
|
Takashi Iwai |
e8a81f |
/* Enter the host, conditionally restoring the host context. */
|
|
Takashi Iwai |
e8a81f |
cbz x29, __host_enter_without_restoring
|
|
Takashi Iwai |
e8a81f |
--
|
|
Takashi Iwai |
e8a81f |
2.26.2
|
|
Takashi Iwai |
e8a81f |
|