Commit 6c3e4422 authored by Suravee Suthikulpanit's avatar Suravee Suthikulpanit Committed by Paolo Bonzini

svm: Add support for dynamic APICv

Add necessary logics to support (de)activate AVIC at runtime.
Signed-off-by: default avatarSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 2de9d0cc
...@@ -387,6 +387,7 @@ static u8 rsm_ins_bytes[] = "\x0f\xaa"; ...@@ -387,6 +387,7 @@ static u8 rsm_ins_bytes[] = "\x0f\xaa";
static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa); static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa);
static void svm_complete_interrupts(struct vcpu_svm *svm); static void svm_complete_interrupts(struct vcpu_svm *svm);
static inline void avic_post_state_restore(struct kvm_vcpu *vcpu);
static int nested_svm_exit_handled(struct vcpu_svm *svm); static int nested_svm_exit_handled(struct vcpu_svm *svm);
static int nested_svm_intercept(struct vcpu_svm *svm); static int nested_svm_intercept(struct vcpu_svm *svm);
...@@ -1545,7 +1546,10 @@ static void avic_init_vmcb(struct vcpu_svm *svm) ...@@ -1545,7 +1546,10 @@ static void avic_init_vmcb(struct vcpu_svm *svm)
vmcb->control.avic_logical_id = lpa & AVIC_HPA_MASK; vmcb->control.avic_logical_id = lpa & AVIC_HPA_MASK;
vmcb->control.avic_physical_id = ppa & AVIC_HPA_MASK; vmcb->control.avic_physical_id = ppa & AVIC_HPA_MASK;
vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID_COUNT; vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID_COUNT;
vmcb->control.int_ctl |= AVIC_ENABLE_MASK; if (kvm_apicv_activated(svm->vcpu.kvm))
vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
else
vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
} }
static void init_vmcb(struct vcpu_svm *svm) static void init_vmcb(struct vcpu_svm *svm)
...@@ -1752,21 +1756,24 @@ static int avic_update_access_page(struct kvm *kvm, bool activate) ...@@ -1752,21 +1756,24 @@ static int avic_update_access_page(struct kvm *kvm, bool activate)
static int avic_init_backing_page(struct kvm_vcpu *vcpu) static int avic_init_backing_page(struct kvm_vcpu *vcpu)
{ {
int ret;
u64 *entry, new_entry; u64 *entry, new_entry;
int id = vcpu->vcpu_id; int id = vcpu->vcpu_id;
struct vcpu_svm *svm = to_svm(vcpu); struct vcpu_svm *svm = to_svm(vcpu);
ret = avic_update_access_page(vcpu->kvm, true);
if (ret)
return ret;
if (id >= AVIC_MAX_PHYSICAL_ID_COUNT) if (id >= AVIC_MAX_PHYSICAL_ID_COUNT)
return -EINVAL; return -EINVAL;
if (!svm->vcpu.arch.apic->regs) if (!svm->vcpu.arch.apic->regs)
return -EINVAL; return -EINVAL;
if (kvm_apicv_activated(vcpu->kvm)) {
int ret;
ret = avic_update_access_page(vcpu->kvm, true);
if (ret)
return ret;
}
svm->avic_backing_page = virt_to_page(svm->vcpu.arch.apic->regs); svm->avic_backing_page = virt_to_page(svm->vcpu.arch.apic->regs);
/* Setting AVIC backing page address in the phy APIC ID table */ /* Setting AVIC backing page address in the phy APIC ID table */
...@@ -2234,7 +2241,8 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu) ...@@ -2234,7 +2241,8 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu)
/* We initialize this flag to true to make sure that the is_running /* We initialize this flag to true to make sure that the is_running
* bit would be set the first time the vcpu is loaded. * bit would be set the first time the vcpu is loaded.
*/ */
svm->avic_is_running = true; if (irqchip_in_kernel(vcpu->kvm) && kvm_apicv_activated(vcpu->kvm))
svm->avic_is_running = true;
svm->nested.hsave = page_address(hsave_page); svm->nested.hsave = page_address(hsave_page);
...@@ -2359,6 +2367,8 @@ static void svm_vcpu_blocking(struct kvm_vcpu *vcpu) ...@@ -2359,6 +2367,8 @@ static void svm_vcpu_blocking(struct kvm_vcpu *vcpu)
static void svm_vcpu_unblocking(struct kvm_vcpu *vcpu) static void svm_vcpu_unblocking(struct kvm_vcpu *vcpu)
{ {
if (kvm_check_request(KVM_REQ_APICV_UPDATE, vcpu))
kvm_vcpu_update_apicv(vcpu);
avic_set_running(vcpu, true); avic_set_running(vcpu, true);
} }
...@@ -5186,17 +5196,25 @@ static int svm_set_pi_irte_mode(struct kvm_vcpu *vcpu, bool activate) ...@@ -5186,17 +5196,25 @@ static int svm_set_pi_irte_mode(struct kvm_vcpu *vcpu, bool activate)
return ret; return ret;
} }
/* Note: Currently only used by Hyper-V. */
static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
{ {
struct vcpu_svm *svm = to_svm(vcpu); struct vcpu_svm *svm = to_svm(vcpu);
struct vmcb *vmcb = svm->vmcb; struct vmcb *vmcb = svm->vmcb;
bool activated = kvm_vcpu_apicv_active(vcpu); bool activated = kvm_vcpu_apicv_active(vcpu);
if (activated) if (activated) {
/**
* During AVIC temporary deactivation, guest could update
* APIC ID, DFR and LDR registers, which would not be trapped
* by avic_unaccelerated_access_interception(). In this case,
* we need to check and update the AVIC logical APIC ID table
* accordingly before re-activating.
*/
avic_post_state_restore(vcpu);
vmcb->control.int_ctl |= AVIC_ENABLE_MASK; vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
else } else {
vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK; vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
}
mark_dirty(vmcb, VMCB_AVIC); mark_dirty(vmcb, VMCB_AVIC);
svm_set_pi_irte_mode(vcpu, activated); svm_set_pi_irte_mode(vcpu, activated);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment