Skip to content

Commit 880ac60

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Introduce interrupt remapping ops structure
Currently, IOMMU support two interrupt remapping table entry formats, 32-bit (legacy) and 128-bit (GA). The spec also implies that it might support additional modes/formats in the future. So, this patch introduces the new struct amd_irte_ops, which allows the same code to work with different irte formats by providing hooks for various operations on an interrupt remapping table entry. Suggested-by: Joerg Roedel <[email protected]> Signed-off-by: Suravee Suthikulpanit <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent a38180b commit 880ac60

File tree

2 files changed

+205
-5
lines changed

2 files changed

+205
-5
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 185 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3644,11 +3644,12 @@ static int alloc_irq_index(u16 devid, int count)
36443644
return index;
36453645
}
36463646

3647-
static int modify_irte(u16 devid, int index, union irte irte)
3647+
static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte)
36483648
{
36493649
struct irq_remap_table *table;
36503650
struct amd_iommu *iommu;
36513651
unsigned long flags;
3652+
struct irte_ga *entry;
36523653

36533654
iommu = amd_iommu_rlookup_table[devid];
36543655
if (iommu == NULL)
@@ -3659,7 +3660,38 @@ static int modify_irte(u16 devid, int index, union irte irte)
36593660
return -ENOMEM;
36603661

36613662
spin_lock_irqsave(&table->lock, flags);
3662-
table->table[index] = irte.val;
3663+
3664+
entry = (struct irte_ga *)table->table;
3665+
entry = &entry[index];
3666+
entry->lo.fields_remap.valid = 0;
3667+
entry->hi.val = irte->hi.val;
3668+
entry->lo.val = irte->lo.val;
3669+
entry->lo.fields_remap.valid = 1;
3670+
3671+
spin_unlock_irqrestore(&table->lock, flags);
3672+
3673+
iommu_flush_irt(iommu, devid);
3674+
iommu_completion_wait(iommu);
3675+
3676+
return 0;
3677+
}
3678+
3679+
static int modify_irte(u16 devid, int index, union irte *irte)
3680+
{
3681+
struct irq_remap_table *table;
3682+
struct amd_iommu *iommu;
3683+
unsigned long flags;
3684+
3685+
iommu = amd_iommu_rlookup_table[devid];
3686+
if (iommu == NULL)
3687+
return -EINVAL;
3688+
3689+
table = get_irq_table(devid, false);
3690+
if (!table)
3691+
return -ENOMEM;
3692+
3693+
spin_lock_irqsave(&table->lock, flags);
3694+
table->table[index] = irte->val;
36633695
spin_unlock_irqrestore(&table->lock, flags);
36643696

36653697
iommu_flush_irt(iommu, devid);
@@ -3690,6 +3722,134 @@ static void free_irte(u16 devid, int index)
36903722
iommu_completion_wait(iommu);
36913723
}
36923724

3725+
static void irte_prepare(void *entry,
3726+
u32 delivery_mode, u32 dest_mode,
3727+
u8 vector, u32 dest_apicid)
3728+
{
3729+
union irte *irte = (union irte *) entry;
3730+
3731+
irte->val = 0;
3732+
irte->fields.vector = vector;
3733+
irte->fields.int_type = delivery_mode;
3734+
irte->fields.destination = dest_apicid;
3735+
irte->fields.dm = dest_mode;
3736+
irte->fields.valid = 1;
3737+
}
3738+
3739+
static void irte_ga_prepare(void *entry,
3740+
u32 delivery_mode, u32 dest_mode,
3741+
u8 vector, u32 dest_apicid)
3742+
{
3743+
struct irte_ga *irte = (struct irte_ga *) entry;
3744+
3745+
irte->lo.val = 0;
3746+
irte->hi.val = 0;
3747+
irte->lo.fields_remap.guest_mode = 0;
3748+
irte->lo.fields_remap.int_type = delivery_mode;
3749+
irte->lo.fields_remap.dm = dest_mode;
3750+
irte->hi.fields.vector = vector;
3751+
irte->lo.fields_remap.destination = dest_apicid;
3752+
irte->lo.fields_remap.valid = 1;
3753+
}
3754+
3755+
static void irte_activate(void *entry, u16 devid, u16 index)
3756+
{
3757+
union irte *irte = (union irte *) entry;
3758+
3759+
irte->fields.valid = 1;
3760+
modify_irte(devid, index, irte);
3761+
}
3762+
3763+
static void irte_ga_activate(void *entry, u16 devid, u16 index)
3764+
{
3765+
struct irte_ga *irte = (struct irte_ga *) entry;
3766+
3767+
irte->lo.fields_remap.valid = 1;
3768+
modify_irte_ga(devid, index, irte);
3769+
}
3770+
3771+
static void irte_deactivate(void *entry, u16 devid, u16 index)
3772+
{
3773+
union irte *irte = (union irte *) entry;
3774+
3775+
irte->fields.valid = 0;
3776+
modify_irte(devid, index, irte);
3777+
}
3778+
3779+
static void irte_ga_deactivate(void *entry, u16 devid, u16 index)
3780+
{
3781+
struct irte_ga *irte = (struct irte_ga *) entry;
3782+
3783+
irte->lo.fields_remap.valid = 0;
3784+
modify_irte_ga(devid, index, irte);
3785+
}
3786+
3787+
static void irte_set_affinity(void *entry, u16 devid, u16 index,
3788+
u8 vector, u32 dest_apicid)
3789+
{
3790+
union irte *irte = (union irte *) entry;
3791+
3792+
irte->fields.vector = vector;
3793+
irte->fields.destination = dest_apicid;
3794+
modify_irte(devid, index, irte);
3795+
}
3796+
3797+
static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
3798+
u8 vector, u32 dest_apicid)
3799+
{
3800+
struct irte_ga *irte = (struct irte_ga *) entry;
3801+
3802+
irte->hi.fields.vector = vector;
3803+
irte->lo.fields_remap.destination = dest_apicid;
3804+
irte->lo.fields_remap.guest_mode = 0;
3805+
modify_irte_ga(devid, index, irte);
3806+
}
3807+
3808+
static void irte_set_allocated(struct irq_remap_table *table, int index)
3809+
{
3810+
table->table[index] = IRTE_ALLOCATED;
3811+
}
3812+
3813+
static void irte_ga_set_allocated(struct irq_remap_table *table, int index)
3814+
{
3815+
struct irte_ga *ptr = (struct irte_ga *)table->table;
3816+
struct irte_ga *irte = &ptr[index];
3817+
3818+
memset(&irte->lo.val, 0, sizeof(u64));
3819+
memset(&irte->hi.val, 0, sizeof(u64));
3820+
irte->hi.fields.vector = 0xff;
3821+
}
3822+
3823+
static bool irte_is_allocated(struct irq_remap_table *table, int index)
3824+
{
3825+
union irte *ptr = (union irte *)table->table;
3826+
union irte *irte = &ptr[index];
3827+
3828+
return irte->val != 0;
3829+
}
3830+
3831+
static bool irte_ga_is_allocated(struct irq_remap_table *table, int index)
3832+
{
3833+
struct irte_ga *ptr = (struct irte_ga *)table->table;
3834+
struct irte_ga *irte = &ptr[index];
3835+
3836+
return irte->hi.fields.vector != 0;
3837+
}
3838+
3839+
static void irte_clear_allocated(struct irq_remap_table *table, int index)
3840+
{
3841+
table->table[index] = 0;
3842+
}
3843+
3844+
static void irte_ga_clear_allocated(struct irq_remap_table *table, int index)
3845+
{
3846+
struct irte_ga *ptr = (struct irte_ga *)table->table;
3847+
struct irte_ga *irte = &ptr[index];
3848+
3849+
memset(&irte->lo.val, 0, sizeof(u64));
3850+
memset(&irte->hi.val, 0, sizeof(u64));
3851+
}
3852+
36933853
static int get_devid(struct irq_alloc_info *info)
36943854
{
36953855
int devid = -1;
@@ -3817,6 +3977,26 @@ static void irq_remapping_prepare_irte(struct amd_ir_data *data,
38173977
}
38183978
}
38193979

3980+
struct amd_irte_ops irte_32_ops = {
3981+
.prepare = irte_prepare,
3982+
.activate = irte_activate,
3983+
.deactivate = irte_deactivate,
3984+
.set_affinity = irte_set_affinity,
3985+
.set_allocated = irte_set_allocated,
3986+
.is_allocated = irte_is_allocated,
3987+
.clear_allocated = irte_clear_allocated,
3988+
};
3989+
3990+
struct amd_irte_ops irte_128_ops = {
3991+
.prepare = irte_ga_prepare,
3992+
.activate = irte_ga_activate,
3993+
.deactivate = irte_ga_deactivate,
3994+
.set_affinity = irte_ga_set_affinity,
3995+
.set_allocated = irte_ga_set_allocated,
3996+
.is_allocated = irte_ga_is_allocated,
3997+
.clear_allocated = irte_ga_clear_allocated,
3998+
};
3999+
38204000
static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
38214001
unsigned int nr_irqs, void *arg)
38224002
{
@@ -3922,7 +4102,7 @@ static void irq_remapping_activate(struct irq_domain *domain,
39224102
struct amd_ir_data *data = irq_data->chip_data;
39234103
struct irq_2_irte *irte_info = &data->irq_2_irte;
39244104

3925-
modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
4105+
modify_irte(irte_info->devid, irte_info->index, &data->irte_entry);
39264106
}
39274107

39284108
static void irq_remapping_deactivate(struct irq_domain *domain,
@@ -3933,7 +4113,7 @@ static void irq_remapping_deactivate(struct irq_domain *domain,
39334113
union irte entry;
39344114

39354115
entry.val = 0;
3936-
modify_irte(irte_info->devid, irte_info->index, data->irte_entry);
4116+
modify_irte(irte_info->devid, irte_info->index, &data->irte_entry);
39374117
}
39384118

39394119
static struct irq_domain_ops amd_ir_domain_ops = {
@@ -3962,7 +4142,7 @@ static int amd_ir_set_affinity(struct irq_data *data,
39624142
*/
39634143
ir_data->irte_entry.fields.vector = cfg->vector;
39644144
ir_data->irte_entry.fields.destination = cfg->dest_apicid;
3965-
modify_irte(irte_info->devid, irte_info->index, ir_data->irte_entry);
4145+
modify_irte(irte_info->devid, irte_info->index, &ir_data->irte_entry);
39664146

39674147
/*
39684148
* After this point, all the interrupts will start arriving

drivers/iommu/amd_iommu_types.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ struct amd_iommu_fault {
410410

411411
struct iommu_domain;
412412
struct irq_domain;
413+
struct amd_irte_ops;
413414

414415
/*
415416
* This structure contains generic data for IOMMU protection domains
@@ -533,6 +534,8 @@ struct amd_iommu {
533534
#ifdef CONFIG_IRQ_REMAP
534535
struct irq_domain *ir_domain;
535536
struct irq_domain *msi_domain;
537+
538+
struct amd_irte_ops *irte_ops;
536539
#endif
537540
};
538541

@@ -779,6 +782,23 @@ struct amd_ir_data {
779782
struct irq_2_irte irq_2_irte;
780783
union irte irte_entry;
781784
struct msi_msg msi_entry;
785+
void *entry; /* Pointer to union irte or struct irte_ga */
786+
};
787+
788+
struct amd_irte_ops {
789+
void (*prepare)(void *, u32, u32, u8, u32);
790+
void (*activate)(void *, u16, u16);
791+
void (*deactivate)(void *, u16, u16);
792+
void (*set_affinity)(void *, u16, u16, u8, u32);
793+
void *(*get)(struct irq_remap_table *, int);
794+
void (*set_allocated)(struct irq_remap_table *, int);
795+
bool (*is_allocated)(struct irq_remap_table *, int);
796+
void (*clear_allocated)(struct irq_remap_table *, int);
782797
};
783798

799+
#ifdef CONFIG_IRQ_REMAP
800+
extern struct amd_irte_ops irte_32_ops;
801+
extern struct amd_irte_ops irte_128_ops;
802+
#endif
803+
784804
#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */

0 commit comments

Comments
 (0)