lkml.org 
[lkml]   [2016]   [Apr]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PART2 RFC v1 9/9] svm: Update AMD IOMMU IRTE with vcpu scheduling information when enable AVIC
    Date
    From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>

    In case AVIC is enabled, during vcpu_load/unload, SVM needs to update
    IOMMU IRTE with appropriate host physical APIC ID. Also, when
    vcpu_blocking/unblocking, SVM needs to update the is-running bit in
    the IOMMU IRTE. Both are achieved via calling amd_iommu_update_ga().

    However, if GA mode is not enabled for the pass-through device,
    IOMMU driver will simply just return when calling amd_iommu_update_ga.

    Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
    ---
    arch/x86/kvm/svm.c | 50 +++++++++++++++++++++++++++++++++++++++++++-------
    1 file changed, 43 insertions(+), 7 deletions(-)

    diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
    index 38fd7a3..3b9a0b2 100644
    --- a/arch/x86/kvm/svm.c
    +++ b/arch/x86/kvm/svm.c
    @@ -1397,11 +1397,24 @@ free_avic:
    return err;
    }

    +static inline int
    +avic_update_iommu(struct kvm_vcpu *vcpu, int cpu, phys_addr_t pa, bool r)
    +{
    + struct kvm_arch *vm_data = &vcpu->kvm->arch;
    +
    + if (!kvm_arch_has_assigned_device(vcpu->kvm))
    + return 0;
    +
    + return amd_iommu_update_ga(vcpu->vcpu_id, cpu, vm_data->avic_tag,
    + (pa & AVIC_HPA_MASK), r);
    +}
    +
    /**
    * This function is called during VCPU halt/unhalt.
    */
    static int avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
    {
    + int ret = 0;
    u64 entry;
    int h_physical_id = __default_cpu_present_to_apicid(vcpu->cpu);
    struct vcpu_svm *svm = to_svm(vcpu);
    @@ -1420,17 +1433,27 @@ static int avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
    WARN_ON((entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) == 0);

    entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
    - if (is_run)
    + if (is_run) {
    entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
    - WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
    + WRITE_ONCE(*(svm->avic_physical_id_cache), entry);

    - return 0;
    + ret = avic_update_iommu(vcpu, h_physical_id,
    + page_to_phys(svm->avic_backing_page), 1);
    + } else {
    + ret = avic_update_iommu(vcpu, h_physical_id,
    + page_to_phys(svm->avic_backing_page), 0);
    +
    + WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
    + }
    +
    + return ret;
    }

    static int avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu, bool is_load)
    {
    - u64 entry;
    + int ret = 0;
    int h_physical_id = __default_cpu_present_to_apicid(cpu);
    + u64 entry;
    struct vcpu_svm *svm = to_svm(vcpu);

    if (!svm_vcpu_avic_enabled(svm))
    @@ -1443,16 +1466,29 @@ static int avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu, bool is_load)
    entry = READ_ONCE(*(svm->avic_physical_id_cache));
    WARN_ON(is_load && (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK));

    - entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
    if (is_load) {
    entry &= ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
    entry |= (h_physical_id & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK);
    +
    + entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
    if (!svm->avic_is_blocking)
    entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
    + WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
    +
    + ret = avic_update_iommu(vcpu, h_physical_id,
    + page_to_phys(svm->avic_backing_page),
    + !svm->avic_is_blocking);
    + } else {
    + if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) {
    + ret = avic_update_iommu(vcpu, h_physical_id,
    + page_to_phys(svm->avic_backing_page), 0);
    +
    + entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
    + WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
    + }
    }
    - WRITE_ONCE(*(svm->avic_physical_id_cache), entry);

    - return 0;
    + return ret;
    }

    static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
    --
    1.9.1
    \
     
     \ /
      Last update: 2016-04-08 15:41    [W:3.531 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site