From 686d4dd0f9d8668b58239a5d35459436b6c62d09 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 24 Feb 2022 14:46:45 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Clear pvmfw pages on clean host shutdown When the host shuts down cleanly under pKVM, it is EL2's responsibility to clear the pvmfw pages before forwarding the PSCI call onto EL3. Wipe the pvmfw pages on SYSTEM_OFF, SYSTEM_RESET and SYSTEM_RESET2 calls from the host, cleaning the zeroed memory to the PoC for good measure. Reported-by: Andrew Scull Bug: 196204410 Signed-off-by: Will Deacon Change-Id: I0dd2757e355f384813319034c6eed0fa2c2328c2 --- arch/arm64/kvm/hyp/include/nvhe/pkvm.h | 1 + arch/arm64/kvm/hyp/nvhe/pkvm.c | 8 ++++++++ arch/arm64/kvm/hyp/nvhe/psci-relay.c | 6 +++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h index ddb64ba46aa4..05bd6c2d04af 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h +++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h @@ -99,5 +99,6 @@ static inline bool ipa_in_pvmfw_region(struct kvm_shadow_vm *vm, u64 ipa) int pkvm_load_pvmfw_pages(struct kvm_shadow_vm *vm, u64 ipa, phys_addr_t phys, u64 size); +void pkvm_clear_pvmfw_pages(void); #endif /* __ARM64_KVM_NVHE_PKVM_H__ */ diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 09dc651647fb..0b1ec45449d5 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -712,6 +712,14 @@ int pkvm_load_pvmfw_pages(struct kvm_shadow_vm *vm, u64 ipa, phys_addr_t phys, return 0; } +void pkvm_clear_pvmfw_pages(void) +{ + void *addr = hyp_phys_to_virt(pvmfw_base); + + memset(addr, 0, pvmfw_size); + kvm_flush_dcache_to_poc(addr, pvmfw_size); +} + /* * This function sets the registers on the vcpu to their architecturally defined * reset values. diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c index 08508783ec3d..cee6d4a2821f 100644 --- a/arch/arm64/kvm/hyp/nvhe/psci-relay.c +++ b/arch/arm64/kvm/hyp/nvhe/psci-relay.c @@ -12,6 +12,7 @@ #include #include +#include #include void kvm_hyp_cpu_entry(unsigned long r0); @@ -249,6 +250,7 @@ static unsigned long psci_0_2_handler(u64 func_id, struct kvm_cpu_context *host_ */ case PSCI_0_2_FN_SYSTEM_OFF: case PSCI_0_2_FN_SYSTEM_RESET: + pkvm_clear_pvmfw_pages(); return psci_forward(host_ctxt); case PSCI_0_2_FN64_CPU_SUSPEND: return psci_cpu_suspend(func_id, host_ctxt); @@ -262,9 +264,11 @@ static unsigned long psci_0_2_handler(u64 func_id, struct kvm_cpu_context *host_ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_ctxt) { switch (func_id) { + case PSCI_1_1_FN64_SYSTEM_RESET2: + pkvm_clear_pvmfw_pages(); + fallthrough; case PSCI_1_0_FN_PSCI_FEATURES: case PSCI_1_0_FN_SET_SUSPEND_MODE: - case PSCI_1_1_FN64_SYSTEM_RESET2: return psci_forward(host_ctxt); case PSCI_1_0_FN64_SYSTEM_SUSPEND: return psci_system_suspend(func_id, host_ctxt);