The cpuidle-haltpoll driver with haltpoll governor allows the guest vcpus to poll for a specified amount of time before halting. This provides some benefits such as avoid sending IPI to perform a wakeup and avoid VM-exit cost. When guest VM uses cpuidle-halt poll method, haltpoll need be disabled at host hypervisor side to avoid double haltpoll in both guest VM and host hypervisor. Here KVM_FEATURE_POLL_CONTROL feature is added in KVM and guest can detect this feature and disable haltpoll in host side. Signed-off-by: Bibo Mao <maobibo@xxxxxxxxxxx> --- arch/loongarch/include/asm/kvm_host.h | 1 + arch/loongarch/include/asm/loongarch.h | 1 + arch/loongarch/include/uapi/asm/kvm.h | 3 + arch/loongarch/kvm/Kconfig | 1 + arch/loongarch/kvm/exit.c | 9 ++- arch/loongarch/kvm/vcpu.c | 85 ++++++++++++++++++++------ 6 files changed, 81 insertions(+), 19 deletions(-) diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h index 44b54965f5b4..a972f70ccdfc 100644 --- a/arch/loongarch/include/asm/kvm_host.h +++ b/arch/loongarch/include/asm/kvm_host.h @@ -214,6 +214,7 @@ struct kvm_vcpu_arch { u64 last_steal; struct gfn_to_hva_cache cache; } st; + unsigned long kvm_poll_control; }; static inline unsigned long readl_sw_gcsr(struct loongarch_csrs *csr, int reg) diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index 04a78010fc72..e4fc30cf3572 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -170,6 +170,7 @@ #define CPUCFG_KVM_FEATURE (CPUCFG_KVM_BASE + 4) #define KVM_FEATURE_IPI BIT(1) #define KVM_FEATURE_STEAL_TIME BIT(2) +#define KVM_FEATURE_POLL_CONTROL BIT(3) #ifndef __ASSEMBLY__ diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h index ddc5cab0ffd0..191f10c2b6c2 100644 --- a/arch/loongarch/include/uapi/asm/kvm.h +++ b/arch/loongarch/include/uapi/asm/kvm.h @@ -85,7 +85,10 @@ struct kvm_fpu { /* Device Control API on vcpu fd */ #define KVM_LOONGARCH_VCPU_CPUCFG 0 #define KVM_LOONGARCH_VCPU_PVTIME_CTRL 1 +/* Alias of KVM_LOONGARCH_VCPU_PVTIME_CTRL for wider use */ +#define KVM_LOONGARCH_VCPU_PV_CTRL 1 #define KVM_LOONGARCH_VCPU_PVTIME_GPA 0 +#define KVM_LOONGARCH_VCPU_POLL_CTRL 1 struct kvm_debug_exit_arch { }; diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig index 248744b4d086..c5cc4dd2fb90 100644 --- a/arch/loongarch/kvm/Kconfig +++ b/arch/loongarch/kvm/Kconfig @@ -21,6 +21,7 @@ config KVM tristate "Kernel-based Virtual Machine (KVM) support" depends on AS_HAS_LVZ_EXTENSION select HAVE_KVM_DIRTY_RING_ACQ_REL + select HAVE_KVM_NO_POLL select HAVE_KVM_VCPU_ASYNC_IOCTL select KVM_COMMON select KVM_GENERIC_DIRTYLOG_READ_PROTECT diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c index ea73f9dc2cc6..ebd578251388 100644 --- a/arch/loongarch/kvm/exit.c +++ b/arch/loongarch/kvm/exit.c @@ -50,7 +50,7 @@ static int kvm_emu_cpucfg(struct kvm_vcpu *vcpu, larch_inst inst) vcpu->arch.gprs[rd] = *(unsigned int *)KVM_SIGNATURE; break; case CPUCFG_KVM_FEATURE: - ret = KVM_FEATURE_IPI; + ret = KVM_FEATURE_IPI | KVM_FEATURE_POLL_CONTROL; if (kvm_pvtime_supported()) ret |= KVM_FEATURE_STEAL_TIME; vcpu->arch.gprs[rd] = ret; @@ -711,6 +711,13 @@ static long kvm_save_notify(struct kvm_vcpu *vcpu) vcpu->arch.st.last_steal = current->sched_info.run_delay; kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); break; + case KVM_FEATURE_POLL_CONTROL: + /* Only enable bit supported */ + if (data & (-1ULL << 1)) + return KVM_HCALL_INVALID_PARAMETER; + + vcpu->arch.kvm_poll_control = data; + break; default: break; }; diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index 16756ffb55e8..6e5c58cef90f 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -233,6 +233,11 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE; } +bool kvm_arch_no_poll(struct kvm_vcpu *vcpu) +{ + return (vcpu->arch.kvm_poll_control & 1) == 0; +} + bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu) { return false; @@ -650,6 +655,7 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu, kvm_reset_timer(vcpu); memset(&vcpu->arch.irq_pending, 0, sizeof(vcpu->arch.irq_pending)); memset(&vcpu->arch.irq_clear, 0, sizeof(vcpu->arch.irq_clear)); + vcpu->arch.kvm_poll_control = 1; break; default: ret = -EINVAL; @@ -737,14 +743,21 @@ static int kvm_loongarch_cpucfg_has_attr(struct kvm_vcpu *vcpu, return -ENXIO; } -static int kvm_loongarch_pvtime_has_attr(struct kvm_vcpu *vcpu, +static int kvm_loongarch_pv_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { - if (!kvm_pvtime_supported() || - attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) + switch (attr->attr) { + case KVM_LOONGARCH_VCPU_PVTIME_GPA: + if (!kvm_pvtime_supported()) + return -ENXIO; + return 0; + case KVM_LOONGARCH_VCPU_POLL_CTRL: + return 0; + default: return -ENXIO; + } - return 0; + return -ENXIO; } static int kvm_loongarch_vcpu_has_attr(struct kvm_vcpu *vcpu, @@ -756,8 +769,8 @@ static int kvm_loongarch_vcpu_has_attr(struct kvm_vcpu *vcpu, case KVM_LOONGARCH_VCPU_CPUCFG: ret = kvm_loongarch_cpucfg_has_attr(vcpu, attr); break; - case KVM_LOONGARCH_VCPU_PVTIME_CTRL: - ret = kvm_loongarch_pvtime_has_attr(vcpu, attr); + case KVM_LOONGARCH_VCPU_PV_CTRL: + ret = kvm_loongarch_pv_has_attr(vcpu, attr); break; default: break; @@ -782,18 +795,26 @@ static int kvm_loongarch_cpucfg_get_attr(struct kvm_vcpu *vcpu, return ret; } -static int kvm_loongarch_pvtime_get_attr(struct kvm_vcpu *vcpu, +static int kvm_loongarch_pv_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { - u64 gpa; + u64 val; u64 __user *user = (u64 __user *)attr->addr; - if (!kvm_pvtime_supported() || - attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) + switch (attr->attr) { + case KVM_LOONGARCH_VCPU_PVTIME_GPA: + if (!kvm_pvtime_supported()) + return -ENXIO; + val = vcpu->arch.st.guest_addr; + break; + case KVM_LOONGARCH_VCPU_POLL_CTRL: + val = vcpu->arch.kvm_poll_control; + break; + default: return -ENXIO; + } - gpa = vcpu->arch.st.guest_addr; - if (put_user(gpa, user)) + if (put_user(val, user)) return -EFAULT; return 0; @@ -808,8 +829,8 @@ static int kvm_loongarch_vcpu_get_attr(struct kvm_vcpu *vcpu, case KVM_LOONGARCH_VCPU_CPUCFG: ret = kvm_loongarch_cpucfg_get_attr(vcpu, attr); break; - case KVM_LOONGARCH_VCPU_PVTIME_CTRL: - ret = kvm_loongarch_pvtime_get_attr(vcpu, attr); + case KVM_LOONGARCH_VCPU_PV_CTRL: + ret = kvm_loongarch_pv_get_attr(vcpu, attr); break; default: break; @@ -831,8 +852,7 @@ static int kvm_loongarch_pvtime_set_attr(struct kvm_vcpu *vcpu, u64 gpa, __user *user = (u64 __user *)attr->addr; struct kvm *kvm = vcpu->kvm; - if (!kvm_pvtime_supported() || - attr->attr != KVM_LOONGARCH_VCPU_PVTIME_GPA) + if (!kvm_pvtime_supported()) return -ENXIO; if (get_user(gpa, user)) @@ -861,6 +881,33 @@ static int kvm_loongarch_pvtime_set_attr(struct kvm_vcpu *vcpu, return ret; } +static int kvm_loongarch_pv_set_attr(struct kvm_vcpu *vcpu, + struct kvm_device_attr *attr) +{ + u64 val, __user *user = (u64 __user *)attr->addr; + + switch (attr->attr) { + case KVM_LOONGARCH_VCPU_PVTIME_GPA: + return kvm_loongarch_pvtime_set_attr(vcpu, attr); + + case KVM_LOONGARCH_VCPU_POLL_CTRL: + if (get_user(val, user)) + return -EFAULT; + + /* Only enable bit supported */ + if (val & (-1ULL << 1)) + return -EINVAL; + + vcpu->arch.kvm_poll_control = val; + break; + + default: + return -ENXIO; + } + + return -ENXIO; +} + static int kvm_loongarch_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) { @@ -870,8 +917,8 @@ static int kvm_loongarch_vcpu_set_attr(struct kvm_vcpu *vcpu, case KVM_LOONGARCH_VCPU_CPUCFG: ret = kvm_loongarch_cpucfg_set_attr(vcpu, attr); break; - case KVM_LOONGARCH_VCPU_PVTIME_CTRL: - ret = kvm_loongarch_pvtime_set_attr(vcpu, attr); + case KVM_LOONGARCH_VCPU_PV_CTRL: + ret = kvm_loongarch_pv_set_attr(vcpu, attr); break; default: break; @@ -1179,6 +1226,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) /* Start with no pending virtual guest interrupts */ csr->csrs[LOONGARCH_CSR_GINTC] = 0; + /* poll control enabled by default */ + vcpu->arch.kvm_poll_control = 1; return 0; } base-commit: de9c2c66ad8e787abec7c9d7eff4f8c3cdd28aed -- 2.39.3