Skip to content

Commit 90fcffd

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Add support for IOMMU XT mode
The AMD IOMMU XT mode enables interrupt remapping with 32-bit destination APIC ID, which is required for x2APIC. The feature is available when the XTSup bit is set in the IOMMU Extended Feature register and/or the IVHD Type 10h IOMMU Feature Reporting field. For more information, please see section "IOMMU x2APIC Support" of the AMD I/O Virtualization Technology (IOMMU) Specification. Cc: Joerg Roedel <[email protected]> Signed-off-by: Suravee Suthikulpanit <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent e881dbd commit 90fcffd

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3876,7 +3876,8 @@ static void irte_ga_prepare(void *entry,
38763876
irte->lo.fields_remap.int_type = delivery_mode;
38773877
irte->lo.fields_remap.dm = dest_mode;
38783878
irte->hi.fields.vector = vector;
3879-
irte->lo.fields_remap.destination = dest_apicid;
3879+
irte->lo.fields_remap.destination = APICID_TO_IRTE_DEST_LO(dest_apicid);
3880+
irte->hi.fields.destination = APICID_TO_IRTE_DEST_HI(dest_apicid);
38803881
irte->lo.fields_remap.valid = 1;
38813882
}
38823883

@@ -3929,7 +3930,10 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
39293930

39303931
if (!irte->lo.fields_remap.guest_mode) {
39313932
irte->hi.fields.vector = vector;
3932-
irte->lo.fields_remap.destination = dest_apicid;
3933+
irte->lo.fields_remap.destination =
3934+
APICID_TO_IRTE_DEST_LO(dest_apicid);
3935+
irte->hi.fields.destination =
3936+
APICID_TO_IRTE_DEST_HI(dest_apicid);
39333937
modify_irte_ga(devid, index, irte, NULL);
39343938
}
39353939
}
@@ -4346,7 +4350,10 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
43464350
irte->lo.val = 0;
43474351
irte->hi.fields.vector = cfg->vector;
43484352
irte->lo.fields_remap.guest_mode = 0;
4349-
irte->lo.fields_remap.destination = cfg->dest_apicid;
4353+
irte->lo.fields_remap.destination =
4354+
APICID_TO_IRTE_DEST_LO(cfg->dest_apicid);
4355+
irte->hi.fields.destination =
4356+
APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
43504357
irte->lo.fields_remap.int_type = apic->irq_delivery_mode;
43514358
irte->lo.fields_remap.dm = apic->irq_dest_mode;
43524359

@@ -4463,8 +4470,12 @@ int amd_iommu_update_ga(int cpu, bool is_run, void *data)
44634470
raw_spin_lock_irqsave(&table->lock, flags);
44644471

44654472
if (ref->lo.fields_vapic.guest_mode) {
4466-
if (cpu >= 0)
4467-
ref->lo.fields_vapic.destination = cpu;
4473+
if (cpu >= 0) {
4474+
ref->lo.fields_vapic.destination =
4475+
APICID_TO_IRTE_DEST_LO(cpu);
4476+
ref->hi.fields.destination =
4477+
APICID_TO_IRTE_DEST_HI(cpu);
4478+
}
44684479
ref->lo.fields_vapic.is_run = is_run;
44694480
barrier();
44704481
}

drivers/iommu/amd_iommu_init.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ bool amd_iommu_dump;
153153
bool amd_iommu_irq_remap __read_mostly;
154154

155155
int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
156+
static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
156157

157158
static bool amd_iommu_detected;
158159
static bool __initdata amd_iommu_disabled;
@@ -827,6 +828,19 @@ static int iommu_init_ga(struct amd_iommu *iommu)
827828
return ret;
828829
}
829830

831+
static void iommu_enable_xt(struct amd_iommu *iommu)
832+
{
833+
#ifdef CONFIG_IRQ_REMAP
834+
/*
835+
* XT mode (32-bit APIC destination ID) requires
836+
* GA mode (128-bit IRTE support) as a prerequisite.
837+
*/
838+
if (AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir) &&
839+
amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
840+
iommu_feature_enable(iommu, CONTROL_XT_EN);
841+
#endif /* CONFIG_IRQ_REMAP */
842+
}
843+
830844
static void iommu_enable_gt(struct amd_iommu *iommu)
831845
{
832846
if (!iommu_feature(iommu, FEATURE_GT))
@@ -1507,6 +1521,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
15071521
iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
15081522
if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
15091523
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
1524+
if (((h->efr_attr & (0x1 << IOMMU_FEAT_XTSUP_SHIFT)) == 0))
1525+
amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
15101526
break;
15111527
case 0x11:
15121528
case 0x40:
@@ -1516,6 +1532,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
15161532
iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
15171533
if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
15181534
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
1535+
if (((h->efr_reg & (0x1 << IOMMU_EFR_XTSUP_SHIFT)) == 0))
1536+
amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
15191537
break;
15201538
default:
15211539
return -EINVAL;
@@ -1832,6 +1850,8 @@ static void print_iommu_info(void)
18321850
pr_info("AMD-Vi: Interrupt remapping enabled\n");
18331851
if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
18341852
pr_info("AMD-Vi: virtual APIC enabled\n");
1853+
if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
1854+
pr_info("AMD-Vi: X2APIC enabled\n");
18351855
}
18361856
}
18371857

@@ -2168,6 +2188,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
21682188
iommu_enable_event_buffer(iommu);
21692189
iommu_set_exclusion_range(iommu);
21702190
iommu_enable_ga(iommu);
2191+
iommu_enable_xt(iommu);
21712192
iommu_enable(iommu);
21722193
iommu_flush_all_caches(iommu);
21732194
}
@@ -2212,6 +2233,7 @@ static void early_enable_iommus(void)
22122233
iommu_enable_command_buffer(iommu);
22132234
iommu_enable_event_buffer(iommu);
22142235
iommu_enable_ga(iommu);
2236+
iommu_enable_xt(iommu);
22152237
iommu_set_device_table(iommu);
22162238
iommu_flush_all_caches(iommu);
22172239
}
@@ -2691,8 +2713,7 @@ int __init amd_iommu_enable(void)
26912713
return ret;
26922714

26932715
irq_remapping_enabled = 1;
2694-
2695-
return 0;
2716+
return amd_iommu_xt_mode;
26962717
}
26972718

26982719
void amd_iommu_disable(void)

drivers/iommu/amd_iommu_types.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
#define CONTROL_GAM_EN 0x19ULL
162162
#define CONTROL_GALOG_EN 0x1CULL
163163
#define CONTROL_GAINT_EN 0x1DULL
164+
#define CONTROL_XT_EN 0x32ULL
164165

165166
#define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT)
166167
#define CTRL_INV_TO_NONE 0
@@ -378,9 +379,11 @@
378379
#define IOMMU_CAP_EFR 27
379380

380381
/* IOMMU Feature Reporting Field (for IVHD type 10h */
382+
#define IOMMU_FEAT_XTSUP_SHIFT 0
381383
#define IOMMU_FEAT_GASUP_SHIFT 6
382384

383385
/* IOMMU Extended Feature Register (EFR) */
386+
#define IOMMU_EFR_XTSUP_SHIFT 2
384387
#define IOMMU_EFR_GASUP_SHIFT 7
385388

386389
#define MAX_DOMAIN_ID 65536
@@ -437,7 +440,6 @@ extern struct kmem_cache *amd_iommu_irq_cache;
437440
#define APERTURE_RANGE_INDEX(a) ((a) >> APERTURE_RANGE_SHIFT)
438441
#define APERTURE_PAGE_INDEX(a) (((a) >> 21) & 0x3fULL)
439442

440-
441443
/*
442444
* This struct is used to pass information about
443445
* incoming PPR faults around.
@@ -810,6 +812,9 @@ union irte {
810812
} fields;
811813
};
812814

815+
#define APICID_TO_IRTE_DEST_LO(x) (x & 0xffffff)
816+
#define APICID_TO_IRTE_DEST_HI(x) ((x >> 24) & 0xff)
817+
813818
union irte_ga_lo {
814819
u64 val;
815820

@@ -823,8 +828,8 @@ union irte_ga_lo {
823828
dm : 1,
824829
/* ------ */
825830
guest_mode : 1,
826-
destination : 8,
827-
rsvd : 48;
831+
destination : 24,
832+
ga_tag : 32;
828833
} fields_remap;
829834

830835
/* For guest vAPIC */
@@ -837,8 +842,7 @@ union irte_ga_lo {
837842
is_run : 1,
838843
/* ------ */
839844
guest_mode : 1,
840-
destination : 8,
841-
rsvd2 : 16,
845+
destination : 24,
842846
ga_tag : 32;
843847
} fields_vapic;
844848
};
@@ -849,7 +853,8 @@ union irte_ga_hi {
849853
u64 vector : 8,
850854
rsvd_1 : 4,
851855
ga_root_ptr : 40,
852-
rsvd_2 : 12;
856+
rsvd_2 : 4,
857+
destination : 8;
853858
} fields;
854859
};
855860

0 commit comments

Comments
 (0)