aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu.c
diff options
context:
space:
mode:
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>2016-08-23 14:52:39 -0400
committerJoerg Roedel <jroedel@suse.de>2016-09-05 06:41:46 -0400
commitb9fc6b56f478b487dc8fc400da73d89ac9137201 (patch)
treef2bd018bb8dbb4a3c8e28bb3106293e221d3169c /drivers/iommu/amd_iommu.c
parent8dbea3fd7becd4af8ca882c3132be4b1a857e301 (diff)
iommu/amd: Implements irq_set_vcpu_affinity() hook to setup vapic mode for pass-through devices
This patch implements irq_set_vcpu_affinity() function to set up interrupt remapping table entry with vapic mode for pass-through devices. In case requirements for vapic mode are not met, it falls back to set up the IRTE in legacy mode. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/amd_iommu.c')
-rw-r--r--drivers/iommu/amd_iommu.c68
1 files changed, 64 insertions, 4 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 089e1ed4deec..69fc57e0b975 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3718,7 +3718,8 @@ out:
3718 return index; 3718 return index;
3719} 3719}
3720 3720
3721static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte) 3721static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte,
3722 struct amd_ir_data *data)
3722{ 3723{
3723 struct irq_remap_table *table; 3724 struct irq_remap_table *table;
3724 struct amd_iommu *iommu; 3725 struct amd_iommu *iommu;
@@ -3741,6 +3742,8 @@ static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte)
3741 entry->hi.val = irte->hi.val; 3742 entry->hi.val = irte->hi.val;
3742 entry->lo.val = irte->lo.val; 3743 entry->lo.val = irte->lo.val;
3743 entry->lo.fields_remap.valid = 1; 3744 entry->lo.fields_remap.valid = 1;
3745 if (data)
3746 data->ref = entry;
3744 3747
3745 spin_unlock_irqrestore(&table->lock, flags); 3748 spin_unlock_irqrestore(&table->lock, flags);
3746 3749
@@ -3839,7 +3842,7 @@ static void irte_ga_activate(void *entry, u16 devid, u16 index)
3839 struct irte_ga *irte = (struct irte_ga *) entry; 3842 struct irte_ga *irte = (struct irte_ga *) entry;
3840 3843
3841 irte->lo.fields_remap.valid = 1; 3844 irte->lo.fields_remap.valid = 1;
3842 modify_irte_ga(devid, index, irte); 3845 modify_irte_ga(devid, index, irte, NULL);
3843} 3846}
3844 3847
3845static void irte_deactivate(void *entry, u16 devid, u16 index) 3848static void irte_deactivate(void *entry, u16 devid, u16 index)
@@ -3855,7 +3858,7 @@ static void irte_ga_deactivate(void *entry, u16 devid, u16 index)
3855 struct irte_ga *irte = (struct irte_ga *) entry; 3858 struct irte_ga *irte = (struct irte_ga *) entry;
3856 3859
3857 irte->lo.fields_remap.valid = 0; 3860 irte->lo.fields_remap.valid = 0;
3858 modify_irte_ga(devid, index, irte); 3861 modify_irte_ga(devid, index, irte, NULL);
3859} 3862}
3860 3863
3861static void irte_set_affinity(void *entry, u16 devid, u16 index, 3864static void irte_set_affinity(void *entry, u16 devid, u16 index,
@@ -3876,7 +3879,7 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
3876 irte->hi.fields.vector = vector; 3879 irte->hi.fields.vector = vector;
3877 irte->lo.fields_remap.destination = dest_apicid; 3880 irte->lo.fields_remap.destination = dest_apicid;
3878 irte->lo.fields_remap.guest_mode = 0; 3881 irte->lo.fields_remap.guest_mode = 0;
3879 modify_irte_ga(devid, index, irte); 3882 modify_irte_ga(devid, index, irte, NULL);
3880} 3883}
3881 3884
3882#define IRTE_ALLOCATED (~1U) 3885#define IRTE_ALLOCATED (~1U)
@@ -4211,6 +4214,62 @@ static struct irq_domain_ops amd_ir_domain_ops = {
4211 .deactivate = irq_remapping_deactivate, 4214 .deactivate = irq_remapping_deactivate,
4212}; 4215};
4213 4216
4217static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
4218{
4219 struct amd_iommu *iommu;
4220 struct amd_iommu_pi_data *pi_data = vcpu_info;
4221 struct vcpu_data *vcpu_pi_info = pi_data->vcpu_data;
4222 struct amd_ir_data *ir_data = data->chip_data;
4223 struct irte_ga *irte = (struct irte_ga *) ir_data->entry;
4224 struct irq_2_irte *irte_info = &ir_data->irq_2_irte;
4225
4226 pi_data->ir_data = ir_data;
4227
4228 /* Note:
4229 * SVM tries to set up for VAPIC mode, but we are in
4230 * legacy mode. So, we force legacy mode instead.
4231 */
4232 if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) {
4233 pr_debug("AMD-Vi: %s: Fall back to using intr legacy remap\n",
4234 __func__);
4235 pi_data->is_guest_mode = false;
4236 }
4237
4238 iommu = amd_iommu_rlookup_table[irte_info->devid];
4239 if (iommu == NULL)
4240 return -EINVAL;
4241
4242 pi_data->prev_ga_tag = ir_data->cached_ga_tag;
4243 if (pi_data->is_guest_mode) {
4244 /* Setting */
4245 irte->hi.fields.ga_root_ptr = (pi_data->base >> 12);
4246 irte->hi.fields.vector = vcpu_pi_info->vector;
4247 irte->lo.fields_vapic.guest_mode = 1;
4248 irte->lo.fields_vapic.ga_tag = pi_data->ga_tag;
4249
4250 ir_data->cached_ga_tag = pi_data->ga_tag;
4251 } else {
4252 /* Un-Setting */
4253 struct irq_cfg *cfg = irqd_cfg(data);
4254
4255 irte->hi.val = 0;
4256 irte->lo.val = 0;
4257 irte->hi.fields.vector = cfg->vector;
4258 irte->lo.fields_remap.guest_mode = 0;
4259 irte->lo.fields_remap.destination = cfg->dest_apicid;
4260 irte->lo.fields_remap.int_type = apic->irq_delivery_mode;
4261 irte->lo.fields_remap.dm = apic->irq_dest_mode;
4262
4263 /*
4264 * This communicates the ga_tag back to the caller
4265 * so that it can do all the necessary clean up.
4266 */
4267 ir_data->cached_ga_tag = 0;
4268 }
4269
4270 return modify_irte_ga(irte_info->devid, irte_info->index, irte, ir_data);
4271}
4272
4214static int amd_ir_set_affinity(struct irq_data *data, 4273static int amd_ir_set_affinity(struct irq_data *data,
4215 const struct cpumask *mask, bool force) 4274 const struct cpumask *mask, bool force)
4216{ 4275{
@@ -4255,6 +4314,7 @@ static void ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
4255static struct irq_chip amd_ir_chip = { 4314static struct irq_chip amd_ir_chip = {
4256 .irq_ack = ir_ack_apic_edge, 4315 .irq_ack = ir_ack_apic_edge,
4257 .irq_set_affinity = amd_ir_set_affinity, 4316 .irq_set_affinity = amd_ir_set_affinity,
4317 .irq_set_vcpu_affinity = amd_ir_set_vcpu_affinity,
4258 .irq_compose_msi_msg = ir_compose_msi_msg, 4318 .irq_compose_msi_msg = ir_compose_msi_msg,
4259}; 4319};
4260 4320