diff options
author | Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> | 2016-08-23 14:52:38 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-09-05 06:41:46 -0400 |
commit | 8dbea3fd7becd4af8ca882c3132be4b1a857e301 (patch) | |
tree | 08f9aaa6eab2d4139c69acf105b4d80de5c3a1d3 /drivers/iommu | |
parent | bd6fcefc66f6d038406e38edf96a95d9842f819d (diff) |
iommu/amd: Introduce amd_iommu_update_ga()
Introduces a new IOMMU API, amd_iommu_update_ga(), which allows
KVM (SVM) to update existing posted interrupt IOMMU IRTE when
load/unload vcpu.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 39 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 1 |
2 files changed, 40 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index eec37b2f54df..089e1ed4deec 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -4269,4 +4269,43 @@ int amd_iommu_create_irq_domain(struct amd_iommu *iommu) | |||
4269 | 4269 | ||
4270 | return 0; | 4270 | return 0; |
4271 | } | 4271 | } |
4272 | |||
4273 | int amd_iommu_update_ga(int cpu, bool is_run, void *data) | ||
4274 | { | ||
4275 | unsigned long flags; | ||
4276 | struct amd_iommu *iommu; | ||
4277 | struct irq_remap_table *irt; | ||
4278 | struct amd_ir_data *ir_data = (struct amd_ir_data *)data; | ||
4279 | int devid = ir_data->irq_2_irte.devid; | ||
4280 | struct irte_ga *entry = (struct irte_ga *) ir_data->entry; | ||
4281 | struct irte_ga *ref = (struct irte_ga *) ir_data->ref; | ||
4282 | |||
4283 | if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || | ||
4284 | !ref || !entry || !entry->lo.fields_vapic.guest_mode) | ||
4285 | return 0; | ||
4286 | |||
4287 | iommu = amd_iommu_rlookup_table[devid]; | ||
4288 | if (!iommu) | ||
4289 | return -ENODEV; | ||
4290 | |||
4291 | irt = get_irq_table(devid, false); | ||
4292 | if (!irt) | ||
4293 | return -ENODEV; | ||
4294 | |||
4295 | spin_lock_irqsave(&irt->lock, flags); | ||
4296 | |||
4297 | if (ref->lo.fields_vapic.guest_mode) { | ||
4298 | if (cpu >= 0) | ||
4299 | ref->lo.fields_vapic.destination = cpu; | ||
4300 | ref->lo.fields_vapic.is_run = is_run; | ||
4301 | barrier(); | ||
4302 | } | ||
4303 | |||
4304 | spin_unlock_irqrestore(&irt->lock, flags); | ||
4305 | |||
4306 | iommu_flush_irt(iommu, devid); | ||
4307 | iommu_completion_wait(iommu); | ||
4308 | return 0; | ||
4309 | } | ||
4310 | EXPORT_SYMBOL(amd_iommu_update_ga); | ||
4272 | #endif | 4311 | #endif |
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 8a7a93d40063..60018a8fb655 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h | |||
@@ -810,6 +810,7 @@ struct amd_ir_data { | |||
810 | struct irq_2_irte irq_2_irte; | 810 | struct irq_2_irte irq_2_irte; |
811 | struct msi_msg msi_entry; | 811 | struct msi_msg msi_entry; |
812 | void *entry; /* Pointer to union irte or struct irte_ga */ | 812 | void *entry; /* Pointer to union irte or struct irte_ga */ |
813 | void *ref; /* Pointer to the actual irte */ | ||
813 | }; | 814 | }; |
814 | 815 | ||
815 | struct amd_irte_ops { | 816 | struct amd_irte_ops { |