Skip to content

Commit 77bdab4

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Add support for multiple IRTE formats
This patch enables support for the new 128-bit IOMMU IRTE format, which can be used for both legacy and vapic interrupt remapping modes. It replaces the existing operations on IRTE, which can only support the older 32-bit IRTE format, with calls to the new struct amd_irt_ops. It also provides helper functions for setting up, accessing, and updating interrupt remapping table entries in different mode. Signed-off-by: Suravee Suthikulpanit <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent 880ac60 commit 77bdab4

File tree

3 files changed

+50
-25
lines changed

3 files changed

+50
-25
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3532,8 +3532,6 @@ static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
35323532
amd_iommu_dev_table[devid].data[2] = dte;
35333533
}
35343534

3535-
#define IRTE_ALLOCATED (~1U)
3536-
35373535
static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
35383536
{
35393537
struct irq_remap_table *table = NULL;
@@ -3579,13 +3577,18 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
35793577
goto out;
35803578
}
35813579

3582-
memset(table->table, 0, MAX_IRQS_PER_TABLE * sizeof(u32));
3580+
if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
3581+
memset(table->table, 0,
3582+
MAX_IRQS_PER_TABLE * sizeof(u32));
3583+
else
3584+
memset(table->table, 0,
3585+
(MAX_IRQS_PER_TABLE * (sizeof(u64) * 2)));
35833586

35843587
if (ioapic) {
35853588
int i;
35863589

35873590
for (i = 0; i < 32; ++i)
3588-
table->table[i] = IRTE_ALLOCATED;
3591+
iommu->irte_ops->set_allocated(table, i);
35893592
}
35903593

35913594
irq_lookup_table[devid] = table;
@@ -3611,6 +3614,10 @@ static int alloc_irq_index(u16 devid, int count)
36113614
struct irq_remap_table *table;
36123615
unsigned long flags;
36133616
int index, c;
3617+
struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
3618+
3619+
if (!iommu)
3620+
return -ENODEV;
36143621

36153622
table = get_irq_table(devid, false);
36163623
if (!table)
@@ -3622,14 +3629,14 @@ static int alloc_irq_index(u16 devid, int count)
36223629
for (c = 0, index = table->min_index;
36233630
index < MAX_IRQS_PER_TABLE;
36243631
++index) {
3625-
if (table->table[index] == 0)
3632+
if (!iommu->irte_ops->is_allocated(table, index))
36263633
c += 1;
36273634
else
36283635
c = 0;
36293636

36303637
if (c == count) {
36313638
for (; c != 0; --c)
3632-
table->table[index - c + 1] = IRTE_ALLOCATED;
3639+
iommu->irte_ops->set_allocated(table, index - c + 1);
36333640

36343641
index -= count - 1;
36353642
goto out;
@@ -3715,7 +3722,7 @@ static void free_irte(u16 devid, int index)
37153722
return;
37163723

37173724
spin_lock_irqsave(&table->lock, flags);
3718-
table->table[index] = 0;
3725+
iommu->irte_ops->clear_allocated(table, index);
37193726
spin_unlock_irqrestore(&table->lock, flags);
37203727

37213728
iommu_flush_irt(iommu, devid);
@@ -3805,6 +3812,7 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
38053812
modify_irte_ga(devid, index, irte);
38063813
}
38073814

3815+
#define IRTE_ALLOCATED (~1U)
38083816
static void irte_set_allocated(struct irq_remap_table *table, int index)
38093817
{
38103818
table->table[index] = IRTE_ALLOCATED;
@@ -3934,19 +3942,17 @@ static void irq_remapping_prepare_irte(struct amd_ir_data *data,
39343942
{
39353943
struct irq_2_irte *irte_info = &data->irq_2_irte;
39363944
struct msi_msg *msg = &data->msi_entry;
3937-
union irte *irte = &data->irte_entry;
39383945
struct IO_APIC_route_entry *entry;
3946+
struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
3947+
3948+
if (!iommu)
3949+
return;
39393950

39403951
data->irq_2_irte.devid = devid;
39413952
data->irq_2_irte.index = index + sub_handle;
3942-
3943-
/* Setup IRTE for IOMMU */
3944-
irte->val = 0;
3945-
irte->fields.vector = irq_cfg->vector;
3946-
irte->fields.int_type = apic->irq_delivery_mode;
3947-
irte->fields.destination = irq_cfg->dest_apicid;
3948-
irte->fields.dm = apic->irq_dest_mode;
3949-
irte->fields.valid = 1;
3953+
iommu->irte_ops->prepare(data->entry, apic->irq_delivery_mode,
3954+
apic->irq_dest_mode, irq_cfg->vector,
3955+
irq_cfg->dest_apicid);
39503956

39513957
switch (info->type) {
39523958
case X86_IRQ_ALLOC_TYPE_IOAPIC:
@@ -4002,7 +4008,7 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
40024008
{
40034009
struct irq_alloc_info *info = arg;
40044010
struct irq_data *irq_data;
4005-
struct amd_ir_data *data;
4011+
struct amd_ir_data *data = NULL;
40064012
struct irq_cfg *cfg;
40074013
int i, ret, devid;
40084014
int index = -1;
@@ -4054,6 +4060,16 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
40544060
if (!data)
40554061
goto out_free_data;
40564062

4063+
if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
4064+
data->entry = kzalloc(sizeof(union irte), GFP_KERNEL);
4065+
else
4066+
data->entry = kzalloc(sizeof(struct irte_ga),
4067+
GFP_KERNEL);
4068+
if (!data->entry) {
4069+
kfree(data);
4070+
goto out_free_data;
4071+
}
4072+
40574073
irq_data->hwirq = (devid << 16) + i;
40584074
irq_data->chip_data = data;
40594075
irq_data->chip = &amd_ir_chip;
@@ -4090,6 +4106,7 @@ static void irq_remapping_free(struct irq_domain *domain, unsigned int virq,
40904106
data = irq_data->chip_data;
40914107
irte_info = &data->irq_2_irte;
40924108
free_irte(irte_info->devid, irte_info->index);
4109+
kfree(data->entry);
40934110
kfree(data);
40944111
}
40954112
}
@@ -4101,19 +4118,23 @@ static void irq_remapping_activate(struct irq_domain *domain,
41014118
{
41024119
struct amd_ir_data *data = irq_data->chip_data;
41034120
struct irq_2_irte *irte_info = &data->irq_2_irte;
4121+
struct amd_iommu *iommu = amd_iommu_rlookup_table[irte_info->devid];
41044122

4105-
modify_irte(irte_info->devid, irte_info->index, &data->irte_entry);
4123+
if (iommu)
4124+
iommu->irte_ops->activate(data->entry, irte_info->devid,
4125+
irte_info->index);
41064126
}
41074127

41084128
static void irq_remapping_deactivate(struct irq_domain *domain,
41094129
struct irq_data *irq_data)
41104130
{
41114131
struct amd_ir_data *data = irq_data->chip_data;
41124132
struct irq_2_irte *irte_info = &data->irq_2_irte;
4113-
union irte entry;
4133+
struct amd_iommu *iommu = amd_iommu_rlookup_table[irte_info->devid];
41144134

4115-
entry.val = 0;
4116-
modify_irte(irte_info->devid, irte_info->index, &data->irte_entry);
4135+
if (iommu)
4136+
iommu->irte_ops->deactivate(data->entry, irte_info->devid,
4137+
irte_info->index);
41174138
}
41184139

41194140
static struct irq_domain_ops amd_ir_domain_ops = {
@@ -4130,8 +4151,12 @@ static int amd_ir_set_affinity(struct irq_data *data,
41304151
struct irq_2_irte *irte_info = &ir_data->irq_2_irte;
41314152
struct irq_cfg *cfg = irqd_cfg(data);
41324153
struct irq_data *parent = data->parent_data;
4154+
struct amd_iommu *iommu = amd_iommu_rlookup_table[irte_info->devid];
41334155
int ret;
41344156

4157+
if (!iommu)
4158+
return -ENODEV;
4159+
41354160
ret = parent->chip->irq_set_affinity(parent, mask, force);
41364161
if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
41374162
return ret;
@@ -4140,9 +4165,8 @@ static int amd_ir_set_affinity(struct irq_data *data,
41404165
* Atomically updates the IRTE with the new destination, vector
41414166
* and flushes the interrupt entry cache.
41424167
*/
4143-
ir_data->irte_entry.fields.vector = cfg->vector;
4144-
ir_data->irte_entry.fields.destination = cfg->dest_apicid;
4145-
modify_irte(irte_info->devid, irte_info->index, &ir_data->irte_entry);
4168+
iommu->irte_ops->set_affinity(ir_data->entry, irte_info->devid,
4169+
irte_info->index, cfg->vector, cfg->dest_apicid);
41464170

41474171
/*
41484172
* After this point, all the interrupts will start arriving

drivers/iommu/amd_iommu_init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,8 +1893,10 @@ static void iommu_enable_ga(struct amd_iommu *iommu)
18931893
/* Fall through */
18941894
case AMD_IOMMU_GUEST_IR_LEGACY_GA:
18951895
iommu_feature_enable(iommu, CONTROL_GA_EN);
1896+
iommu->irte_ops = &irte_128_ops;
18961897
break;
18971898
default:
1899+
iommu->irte_ops = &irte_32_ops;
18981900
break;
18991901
}
19001902
#endif

drivers/iommu/amd_iommu_types.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,6 @@ struct irq_2_irte {
780780

781781
struct amd_ir_data {
782782
struct irq_2_irte irq_2_irte;
783-
union irte irte_entry;
784783
struct msi_msg msi_entry;
785784
void *entry; /* Pointer to union irte or struct irte_ga */
786785
};

0 commit comments

Comments
 (0)