Skip to content

Commit ca3385a

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/generic-entry into kvmarm-master/next
Switch KVM/arm64 to the generic entry code, courtesy of Oliver Upton * kvm-arm64/generic-entry: KVM: arm64: Use generic KVM xfer to guest work function entry: KVM: Allow use of generic KVM entry w/o full generic support KVM: arm64: Record number of signal exits as a vCPU stat Signed-off-by: Marc Zyngier <[email protected]>
2 parents 78bc117 + 6caa581 commit ca3385a

File tree

5 files changed

+52
-28
lines changed

5 files changed

+52
-28
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ struct kvm_vcpu_stat {
575575
u64 wfi_exit_stat;
576576
u64 mmio_exit_user;
577577
u64 mmio_exit_kernel;
578+
u64 signal_exits;
578579
u64 exits;
579580
};
580581

arch/arm64/kvm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ menuconfig KVM
2626
select HAVE_KVM_ARCH_TLB_FLUSH_ALL
2727
select KVM_MMIO
2828
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
29+
select KVM_XFER_TO_GUEST_WORK
2930
select SRCU
3031
select KVM_VFIO
3132
select HAVE_KVM_EVENTFD

arch/arm64/kvm/arm.c

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <linux/bug.h>
88
#include <linux/cpu_pm.h>
9+
#include <linux/entry-kvm.h>
910
#include <linux/errno.h>
1011
#include <linux/err.h>
1112
#include <linux/kvm_host.h>
@@ -715,6 +716,45 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
715716
static_branch_unlikely(&arm64_mismatched_32bit_el0);
716717
}
717718

719+
/**
720+
* kvm_vcpu_exit_request - returns true if the VCPU should *not* enter the guest
721+
* @vcpu: The VCPU pointer
722+
* @ret: Pointer to write optional return code
723+
*
724+
* Returns: true if the VCPU needs to return to a preemptible + interruptible
725+
* and skip guest entry.
726+
*
727+
* This function disambiguates between two different types of exits: exits to a
728+
* preemptible + interruptible kernel context and exits to userspace. For an
729+
* exit to userspace, this function will write the return code to ret and return
730+
* true. For an exit to preemptible + interruptible kernel context (i.e. check
731+
* for pending work and re-enter), return true without writing to ret.
732+
*/
733+
static bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu, int *ret)
734+
{
735+
struct kvm_run *run = vcpu->run;
736+
737+
/*
738+
* If we're using a userspace irqchip, then check if we need
739+
* to tell a userspace irqchip about timer or PMU level
740+
* changes and if so, exit to userspace (the actual level
741+
* state gets updated in kvm_timer_update_run and
742+
* kvm_pmu_update_run below).
743+
*/
744+
if (static_branch_unlikely(&userspace_irqchip_in_use)) {
745+
if (kvm_timer_should_notify_user(vcpu) ||
746+
kvm_pmu_should_notify_user(vcpu)) {
747+
*ret = -EINTR;
748+
run->exit_reason = KVM_EXIT_INTR;
749+
return true;
750+
}
751+
}
752+
753+
return kvm_request_pending(vcpu) ||
754+
need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid) ||
755+
xfer_to_guest_mode_work_pending();
756+
}
757+
718758
/**
719759
* kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
720760
* @vcpu: The VCPU pointer
@@ -758,7 +798,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
758798
/*
759799
* Check conditions before entering the guest
760800
*/
761-
cond_resched();
801+
ret = xfer_to_guest_mode_handle_work(vcpu);
802+
if (!ret)
803+
ret = 1;
762804

763805
update_vmid(&vcpu->arch.hw_mmu->vmid);
764806

@@ -777,30 +819,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
777819

778820
kvm_vgic_flush_hwstate(vcpu);
779821

780-
/*
781-
* Exit if we have a signal pending so that we can deliver the
782-
* signal to user space.
783-
*/
784-
if (signal_pending(current)) {
785-
ret = -EINTR;
786-
run->exit_reason = KVM_EXIT_INTR;
787-
}
788-
789-
/*
790-
* If we're using a userspace irqchip, then check if we need
791-
* to tell a userspace irqchip about timer or PMU level
792-
* changes and if so, exit to userspace (the actual level
793-
* state gets updated in kvm_timer_update_run and
794-
* kvm_pmu_update_run below).
795-
*/
796-
if (static_branch_unlikely(&userspace_irqchip_in_use)) {
797-
if (kvm_timer_should_notify_user(vcpu) ||
798-
kvm_pmu_should_notify_user(vcpu)) {
799-
ret = -EINTR;
800-
run->exit_reason = KVM_EXIT_INTR;
801-
}
802-
}
803-
804822
/*
805823
* Ensure we set mode to IN_GUEST_MODE after we disable
806824
* interrupts and before the final VCPU requests check.
@@ -809,8 +827,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
809827
*/
810828
smp_store_mb(vcpu->mode, IN_GUEST_MODE);
811829

812-
if (ret <= 0 || need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid) ||
813-
kvm_request_pending(vcpu)) {
830+
if (ret <= 0 || kvm_vcpu_exit_request(vcpu, &ret)) {
814831
vcpu->mode = OUTSIDE_GUEST_MODE;
815832
isb(); /* Ensure work in x_flush_hwstate is committed */
816833
kvm_pmu_sync_hwstate(vcpu);

arch/arm64/kvm/guest.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
5050
STATS_DESC_COUNTER(VCPU, wfi_exit_stat),
5151
STATS_DESC_COUNTER(VCPU, mmio_exit_user),
5252
STATS_DESC_COUNTER(VCPU, mmio_exit_kernel),
53+
STATS_DESC_COUNTER(VCPU, signal_exits),
5354
STATS_DESC_COUNTER(VCPU, exits)
5455
};
5556
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==

include/linux/entry-kvm.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
#ifndef __LINUX_ENTRYKVM_H
33
#define __LINUX_ENTRYKVM_H
44

5-
#include <linux/entry-common.h>
5+
#include <linux/static_call_types.h>
6+
#include <linux/tracehook.h>
7+
#include <linux/syscalls.h>
8+
#include <linux/seccomp.h>
9+
#include <linux/sched.h>
610
#include <linux/tick.h>
711

812
/* Transfer to guest mode work */

0 commit comments

Comments
 (0)