diff --git a/arch/arm64/include/asm/kvm_pkvm_module.h b/arch/arm64/include/asm/kvm_pkvm_module.h index b77d5e8382e4..68b0fbbf2fd4 100644 --- a/arch/arm64/include/asm/kvm_pkvm_module.h +++ b/arch/arm64/include/asm/kvm_pkvm_module.h @@ -32,6 +32,7 @@ struct pkvm_module_ops { int (*register_default_trap_handler)(bool (*cb)(struct kvm_cpu_context *)); int (*register_illegal_abt_notifier)(void (*cb)(struct kvm_cpu_context *)); int (*register_psci_notifier)(void (*cb)(enum pkvm_psci_notification, struct kvm_cpu_context *)); + int (*register_hyp_panic_notifier)(void (*cb)(struct kvm_cpu_context *host_ctxt)); }; struct pkvm_module_section { diff --git a/arch/arm64/kvm/hyp/include/nvhe/modules.h b/arch/arm64/kvm/hyp/include/nvhe/modules.h index 681fd233fd2b..278e53d29f16 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/modules.h +++ b/arch/arm64/kvm/hyp/include/nvhe/modules.h @@ -6,6 +6,7 @@ int __pkvm_register_host_smc_handler(bool (*cb)(struct kvm_cpu_context *)); int __pkvm_register_default_trap_handler(bool (*cb)(struct kvm_cpu_context *)); int __pkvm_register_illegal_abt_notifier(void (*cb)(struct kvm_cpu_context *)); +int __pkvm_register_hyp_panic_notifier(void (*cb)(struct kvm_cpu_context *)); enum pkvm_psci_notification; int __pkvm_register_psci_notifier(void (*cb)(enum pkvm_psci_notification, struct kvm_cpu_context *)); diff --git a/arch/arm64/kvm/hyp/nvhe/modules.c b/arch/arm64/kvm/hyp/nvhe/modules.c index 5b657f80d134..075dfc2b142d 100644 --- a/arch/arm64/kvm/hyp/nvhe/modules.c +++ b/arch/arm64/kvm/hyp/nvhe/modules.c @@ -109,6 +109,7 @@ const struct pkvm_module_ops module_ops = { .register_default_trap_handler = __pkvm_register_default_trap_handler, .register_illegal_abt_notifier = __pkvm_register_illegal_abt_notifier, .register_psci_notifier = __pkvm_register_psci_notifier, + .register_hyp_panic_notifier = __pkvm_register_hyp_panic_notifier, }; int __pkvm_init_module(void *module_init) diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 310aaf493909..0409fb351d85 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -333,6 +333,12 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) return exit_code; } +static void (*hyp_panic_notifier)(struct kvm_cpu_context *host_ctxt); +int __pkvm_register_hyp_panic_notifier(void (*cb)(struct kvm_cpu_context *host_ctxt)) +{ + return cmpxchg(&hyp_panic_notifier, NULL, cb) ? -EBUSY : 0; +} + asmlinkage void __noreturn hyp_panic(void) { u64 spsr = read_sysreg_el2(SYS_SPSR); @@ -344,6 +350,9 @@ asmlinkage void __noreturn hyp_panic(void) host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; vcpu = host_ctxt->__hyp_running_vcpu; + if (READ_ONCE(hyp_panic_notifier)) + hyp_panic_notifier(host_ctxt); + if (vcpu) { __timer_disable_traps(vcpu); __deactivate_traps(vcpu);