Skip to content

Commit 8ca7501

Browse files
mrutland-armgregkh
authored andcommitted
KVM: arm64: Refactor exit handlers
[ Upstream commit 9b66195 ] The hyp exit handling logic is largely shared between VHE and nVHE/hVHE, with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code in the header depends on function definitions provided by arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c when they include the header. This is an unusual header dependency, and prevents the use of arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would result in compiler warnings regarding missing definitions, e.g. | In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8: | ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined | 733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu); | | ^~~~~~~~~~~~~~~~~~~~~~~~~~ | ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined | 735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code); | | ^~~~~~~~~~~~~~~~~ Refactor the logic such that the header doesn't depend on anything from the C files. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <[email protected]> Reviewed-by: Mark Brown <[email protected]> Tested-by: Mark Brown <[email protected]> Acked-by: Will Deacon <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Fuad Tabba <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: Oliver Upton <[email protected]> Reviewed-by: Oliver Upton <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Mark Brown <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 905ca55 commit 8ca7501

File tree

3 files changed

+26
-41
lines changed

3 files changed

+26
-41
lines changed

arch/arm64/kvm/hyp/include/hyp/switch.h

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -666,23 +666,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
666666

667667
typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
668668

669-
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
670-
671-
static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
672-
673669
/*
674670
* Allow the hypervisor to handle the exit with an exit handler if it has one.
675671
*
676672
* Returns true if the hypervisor handled the exit, and control should go back
677673
* to the guest, or false if it hasn't.
678674
*/
679-
static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
675+
static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
676+
const exit_handler_fn *handlers)
680677
{
681-
const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
682-
exit_handler_fn fn;
683-
684-
fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
685-
678+
exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
686679
if (fn)
687680
return fn(vcpu, exit_code);
688681

@@ -712,20 +705,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code
712705
* the guest, false when we should restore the host state and return to the
713706
* main run loop.
714707
*/
715-
static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
708+
static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
709+
const exit_handler_fn *handlers)
716710
{
717-
/*
718-
* Save PSTATE early so that we can evaluate the vcpu mode
719-
* early on.
720-
*/
721-
synchronize_vcpu_pstate(vcpu, exit_code);
722-
723-
/*
724-
* Check whether we want to repaint the state one way or
725-
* another.
726-
*/
727-
early_exit_filter(vcpu, exit_code);
728-
729711
if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
730712
vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
731713

@@ -755,7 +737,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
755737
goto exit;
756738

757739
/* Check if there's an exit handler and allow it to handle the exit. */
758-
if (kvm_hyp_handle_exit(vcpu, exit_code))
740+
if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
759741
goto guest;
760742
exit:
761743
/* Return to the host kernel and handle the exit */

arch/arm64/kvm/hyp/nvhe/switch.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,21 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
224224
return hyp_exit_handlers;
225225
}
226226

227-
/*
228-
* Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
229-
* The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
230-
* guest from dropping to AArch32 EL0 if implemented by the CPU. If the
231-
* hypervisor spots a guest in such a state ensure it is handled, and don't
232-
* trust the host to spot or fix it. The check below is based on the one in
233-
* kvm_arch_vcpu_ioctl_run().
234-
*
235-
* Returns false if the guest ran in AArch32 when it shouldn't have, and
236-
* thus should exit to the host, or true if a the guest run loop can continue.
237-
*/
238-
static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
227+
static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
239228
{
229+
const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
230+
231+
synchronize_vcpu_pstate(vcpu, exit_code);
232+
233+
/*
234+
* Some guests (e.g., protected VMs) are not be allowed to run in
235+
* AArch32. The ARMv8 architecture does not give the hypervisor a
236+
* mechanism to prevent a guest from dropping to AArch32 EL0 if
237+
* implemented by the CPU. If the hypervisor spots a guest in such a
238+
* state ensure it is handled, and don't trust the host to spot or fix
239+
* it. The check below is based on the one in
240+
* kvm_arch_vcpu_ioctl_run().
241+
*/
240242
if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
241243
/*
242244
* As we have caught the guest red-handed, decide that it isn't
@@ -249,6 +251,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
249251
*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
250252
*exit_code |= ARM_EXCEPTION_IL;
251253
}
254+
255+
return __fixup_guest_exit(vcpu, exit_code, handlers);
252256
}
253257

254258
/* Switch to the guest for legacy non-VHE systems */

arch/arm64/kvm/hyp/vhe/switch.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -423,13 +423,10 @@ static const exit_handler_fn hyp_exit_handlers[] = {
423423
[ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops,
424424
};
425425

426-
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
426+
static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
427427
{
428-
return hyp_exit_handlers;
429-
}
428+
synchronize_vcpu_pstate(vcpu, exit_code);
430429

431-
static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
432-
{
433430
/*
434431
* If we were in HYP context on entry, adjust the PSTATE view
435432
* so that the usual helpers work correctly.
@@ -449,6 +446,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
449446
*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
450447
*vcpu_cpsr(vcpu) |= mode;
451448
}
449+
450+
return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
452451
}
453452

454453
/* Switch to the guest for VHE systems running in EL2 */

0 commit comments

Comments
 (0)