diff mbox series

[v4,04/17] kvm: x86: Add support for activate/de-activate APICv at runtime

Message ID 1572648072-84536-5-git-send-email-suravee.suthikulpanit@amd.com (mailing list archive)
State New, archived
Headers show
Series kvm: x86: Support AMD SVM AVIC w/ in-kernel irqchip mode | expand

Commit Message

Suthikulpanit, Suravee Nov. 1, 2019, 10:41 p.m. UTC
Certain runtime conditions require APICv to be temporary deactivated.
However, current implementation only support permanently deactivate
APICv at runtime (mainly used when running Hyper-V synic).

In addition, for AMD, when activate / deactivate APICv during runtime,
all vcpus in the VM has to be operating in the same APICv mode, which
requires the requesting (main) vcpu to notify others.

So, introduce the following:
 * A new KVM_REQ_APICV_UPDATE request bit
 * Interfaces to request all vcpus to update (activate/deactivate) APICv
 * Interface to update APICV-related parameters for each vcpu

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 arch/x86/include/asm/kvm_host.h |  5 +++++
 arch/x86/kvm/x86.c              | 30 ++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

Comments

Paolo Bonzini Nov. 2, 2019, 9:52 a.m. UTC | #1
On 01/11/19 23:41, Suthikulpanit, Suravee wrote:
> +void kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
> +{
> +	if (activate) {
> +		if (!test_and_clear_bit(bit, &kvm->arch.apicv_deact_msk) ||
> +		    !kvm_apicv_activated(kvm))
> +			return;
> +	} else {
> +		if (test_and_set_bit(bit, &kvm->arch.apicv_deact_msk) ||
> +		    kvm_apicv_activated(kvm))
> +			return;
> +	}
> +
> +	kvm_make_all_cpus_request(kvm, KVM_REQ_APICV_UPDATE);
> +}
> +EXPORT_SYMBOL_GPL(kvm_request_apicv_update);
> +

It's worth documenting the locking requirements of
kvm_request_apicv_update (it can also be negative requirements, such as
"don't hold any lock"), because kvm_make_all_cpus_request is a somewhat
deadlock-prone API.

Again, something I'll check after a more thorough review.

Paolo
Suthikulpanit, Suravee Nov. 4, 2019, 7:22 p.m. UTC | #2
Paolo,

On 11/2/19 4:52 AM, Paolo Bonzini wrote:
> On 01/11/19 23:41, Suthikulpanit, Suravee wrote:
>> +void kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
>> +{
>> +	if (activate) {
>> +		if (!test_and_clear_bit(bit, &kvm->arch.apicv_deact_msk) ||
>> +		    !kvm_apicv_activated(kvm))
>> +			return;
>> +	} else {
>> +		if (test_and_set_bit(bit, &kvm->arch.apicv_deact_msk) ||
>> +		    kvm_apicv_activated(kvm))
>> +			return;
>> +	}
>> +
>> +	kvm_make_all_cpus_request(kvm, KVM_REQ_APICV_UPDATE);
>> +}
>> +EXPORT_SYMBOL_GPL(kvm_request_apicv_update);
>> +
> 
> It's worth documenting the locking requirements of
> kvm_request_apicv_update (it can also be negative requirements, such as
> "don't hold any lock"), because kvm_make_all_cpus_request is a somewhat
> deadlock-prone API.

Currently, I have a comment in the svm_request_update_avic(), where it 
calls kvm_request_apicv_update. I'll move it here instead and enhance 
the comment.

Thanks,
Suravee
diff mbox series

Patch

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 1c05363..3b94f42 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -78,6 +78,8 @@ 
 #define KVM_REQ_HV_STIMER		KVM_ARCH_REQ(22)
 #define KVM_REQ_LOAD_EOI_EXITMAP	KVM_ARCH_REQ(23)
 #define KVM_REQ_GET_VMCS12_PAGES	KVM_ARCH_REQ(24)
+#define KVM_REQ_APICV_UPDATE \
+	KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 
 #define CR0_RESERVED_BITS                                               \
 	(~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \
@@ -1421,6 +1423,9 @@  gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva,
 void kvm_vcpu_deactivate_apicv(struct kvm_vcpu *vcpu);
 bool kvm_apicv_activated(struct kvm *kvm);
 void kvm_apicv_init(struct kvm *kvm, bool enable);
+void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu);
+void kvm_request_apicv_update(struct kvm *kvm, bool activate,
+			      unsigned long bit);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 70a70a1..394695a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -26,6 +26,7 @@ 
 #include "cpuid.h"
 #include "pmu.h"
 #include "hyperv.h"
+#include "lapic.h"
 
 #include <linux/clocksource.h>
 #include <linux/interrupt.h>
@@ -7730,6 +7731,33 @@  void kvm_make_scan_ioapic_request(struct kvm *kvm)
 	kvm_make_all_cpus_request(kvm, KVM_REQ_SCAN_IOAPIC);
 }
 
+void kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
+{
+	if (!lapic_in_kernel(vcpu))
+		return;
+
+	vcpu->arch.apicv_active = kvm_apicv_activated(vcpu->kvm);
+	kvm_apic_update_apicv(vcpu);
+	kvm_x86_ops->refresh_apicv_exec_ctrl(vcpu);
+}
+EXPORT_SYMBOL_GPL(kvm_vcpu_update_apicv);
+
+void kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
+{
+	if (activate) {
+		if (!test_and_clear_bit(bit, &kvm->arch.apicv_deact_msk) ||
+		    !kvm_apicv_activated(kvm))
+			return;
+	} else {
+		if (test_and_set_bit(bit, &kvm->arch.apicv_deact_msk) ||
+		    kvm_apicv_activated(kvm))
+			return;
+	}
+
+	kvm_make_all_cpus_request(kvm, KVM_REQ_APICV_UPDATE);
+}
+EXPORT_SYMBOL_GPL(kvm_request_apicv_update);
+
 static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
 {
 	if (!kvm_apic_present(vcpu))
@@ -7916,6 +7944,8 @@  static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 		 */
 		if (kvm_check_request(KVM_REQ_HV_STIMER, vcpu))
 			kvm_hv_process_stimers(vcpu);
+		if (kvm_check_request(KVM_REQ_APICV_UPDATE, vcpu))
+			kvm_vcpu_update_apicv(vcpu);
 	}
 
 	if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {