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 | |
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>
-rw-r--r-- | drivers/iommu/amd_iommu.c | 39 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 1 | ||||
-rw-r--r-- | include/linux/amd-iommu.h | 9 |
3 files changed, 49 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 { |
diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h index 465d096a5f4b..d8d48aca0eb7 100644 --- a/include/linux/amd-iommu.h +++ b/include/linux/amd-iommu.h | |||
@@ -179,6 +179,9 @@ static inline int amd_iommu_detect(void) { return -ENODEV; } | |||
179 | /* IOMMU AVIC Function */ | 179 | /* IOMMU AVIC Function */ |
180 | extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32)); | 180 | extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32)); |
181 | 181 | ||
182 | extern int | ||
183 | amd_iommu_update_ga(int cpu, bool is_run, void *data); | ||
184 | |||
182 | #else /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ | 185 | #else /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ |
183 | 186 | ||
184 | static inline int | 187 | static inline int |
@@ -187,6 +190,12 @@ amd_iommu_register_ga_log_notifier(int (*notifier)(u32)) | |||
187 | return 0; | 190 | return 0; |
188 | } | 191 | } |
189 | 192 | ||
193 | static inline int | ||
194 | amd_iommu_update_ga(int cpu, bool is_run, void *data) | ||
195 | { | ||
196 | return 0; | ||
197 | } | ||
198 | |||
190 | #endif /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ | 199 | #endif /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ |
191 | 200 | ||
192 | #endif /* _ASM_X86_AMD_IOMMU_H */ | 201 | #endif /* _ASM_X86_AMD_IOMMU_H */ |