Skip to content

Commit 9b66195

Browse files
mrutland-armMarc Zyngier
authored andcommitted
KVM: arm64: Refactor exit handlers
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]>
1 parent ee14db3 commit 9b66195

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
@@ -679,23 +679,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code)
679679

680680
typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *);
681681

682-
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu);
683-
684-
static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code);
685-
686682
/*
687683
* Allow the hypervisor to handle the exit with an exit handler if it has one.
688684
*
689685
* Returns true if the hypervisor handled the exit, and control should go back
690686
* to the guest, or false if it hasn't.
691687
*/
692-
static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
688+
static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
689+
const exit_handler_fn *handlers)
693690
{
694-
const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
695-
exit_handler_fn fn;
696-
697-
fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
698-
691+
exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)];
699692
if (fn)
700693
return fn(vcpu, exit_code);
701694

@@ -725,20 +718,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code
725718
* the guest, false when we should restore the host state and return to the
726719
* main run loop.
727720
*/
728-
static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
721+
static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code,
722+
const exit_handler_fn *handlers)
729723
{
730-
/*
731-
* Save PSTATE early so that we can evaluate the vcpu mode
732-
* early on.
733-
*/
734-
synchronize_vcpu_pstate(vcpu, exit_code);
735-
736-
/*
737-
* Check whether we want to repaint the state one way or
738-
* another.
739-
*/
740-
early_exit_filter(vcpu, exit_code);
741-
742724
if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
743725
vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
744726

@@ -768,7 +750,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
768750
goto exit;
769751

770752
/* Check if there's an exit handler and allow it to handle the exit. */
771-
if (kvm_hyp_handle_exit(vcpu, exit_code))
753+
if (kvm_hyp_handle_exit(vcpu, exit_code, handlers))
772754
goto guest;
773755
exit:
774756
/* 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
@@ -250,19 +250,21 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
250250
return hyp_exit_handlers;
251251
}
252252

253-
/*
254-
* Some guests (e.g., protected VMs) are not be allowed to run in AArch32.
255-
* The ARMv8 architecture does not give the hypervisor a mechanism to prevent a
256-
* guest from dropping to AArch32 EL0 if implemented by the CPU. If the
257-
* hypervisor spots a guest in such a state ensure it is handled, and don't
258-
* trust the host to spot or fix it. The check below is based on the one in
259-
* kvm_arch_vcpu_ioctl_run().
260-
*
261-
* Returns false if the guest ran in AArch32 when it shouldn't have, and
262-
* thus should exit to the host, or true if a the guest run loop can continue.
263-
*/
264-
static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
253+
static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
265254
{
255+
const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu);
256+
257+
synchronize_vcpu_pstate(vcpu, exit_code);
258+
259+
/*
260+
* Some guests (e.g., protected VMs) are not be allowed to run in
261+
* AArch32. The ARMv8 architecture does not give the hypervisor a
262+
* mechanism to prevent a guest from dropping to AArch32 EL0 if
263+
* implemented by the CPU. If the hypervisor spots a guest in such a
264+
* state ensure it is handled, and don't trust the host to spot or fix
265+
* it. The check below is based on the one in
266+
* kvm_arch_vcpu_ioctl_run().
267+
*/
266268
if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
267269
/*
268270
* As we have caught the guest red-handed, decide that it isn't
@@ -275,6 +277,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
275277
*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
276278
*exit_code |= ARM_EXCEPTION_IL;
277279
}
280+
281+
return __fixup_guest_exit(vcpu, exit_code, handlers);
278282
}
279283

280284
/* 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
@@ -540,13 +540,10 @@ static const exit_handler_fn hyp_exit_handlers[] = {
540540
[ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops,
541541
};
542542

543-
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
543+
static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
544544
{
545-
return hyp_exit_handlers;
546-
}
545+
synchronize_vcpu_pstate(vcpu, exit_code);
547546

548-
static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
549-
{
550547
/*
551548
* If we were in HYP context on entry, adjust the PSTATE view
552549
* so that the usual helpers work correctly.
@@ -566,6 +563,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
566563
*vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT);
567564
*vcpu_cpsr(vcpu) |= mode;
568565
}
566+
567+
return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers);
569568
}
570569

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

0 commit comments

Comments
 (0)