Message ID | 20231024152105.35942-6-minhquangbui99@gmail.com |
---|---|
State | New |
Headers | show |
Series | [v9,1/5] i386/tcg: implement x2APIC registers MSR access | expand |
On Tue, Oct 24, 2023 at 10:21:05PM +0700, Bui Quang Minh wrote: > This commit adds XTSup configuration to let user choose to whether enable > this feature or not. When XTSup is enabled, additional bytes in IRTE with > enabled guest virtual VAPIC are used to support 32-bit destination id. > > Additionally, this commit exports IVHD type 0x11 besides the old IVHD type > 0x10 in ACPI table. IVHD type 0x10 does not report full set of IOMMU > features only the legacy ones, so operating system (e.g. Linux) may only > detects x2APIC support if IVHD type 0x11 is available. The IVHD type 0x10 > is kept so that old operating system that only parses type 0x10 can detect > the IOMMU device. > > Reviewed-by: Michael S. Tsirkin <mst@redhat.com> > Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com> changes IVRS without updating expected files for tests. result seems to be CI failures: https://gitlab.com/mstredhat/qemu/-/jobs/5470533834 > --- > hw/i386/acpi-build.c | 129 +++++++++++++++++++++++++++---------------- > hw/i386/amd_iommu.c | 29 +++++++++- > hw/i386/amd_iommu.h | 16 ++++-- > 3 files changed, 117 insertions(+), 57 deletions(-) > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > index 3f2b27cf75..8069971e54 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -2337,30 +2337,23 @@ static void > build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, > const char *oem_table_id) > { > - int ivhd_table_len = 24; > AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default()); > GArray *ivhd_blob = g_array_new(false, true, 1); > AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id, > .oem_table_id = oem_table_id }; > + uint64_t feature_report; > > acpi_table_begin(&table, table_data); > /* IVinfo - IO virtualization information common to all > * IOMMU units in a system > */ > - build_append_int_noprefix(table_data, 40UL << 8/* PASize */, 4); > + build_append_int_noprefix(table_data, > + (1UL << 0) | /* EFRSup */ > + (40UL << 8), /* PASize */ > + 4); > /* reserved */ > build_append_int_noprefix(table_data, 0, 8); > > - /* IVHD definition - type 10h */ > - build_append_int_noprefix(table_data, 0x10, 1); > - /* virtualization flags */ > - build_append_int_noprefix(table_data, > - (1UL << 0) | /* HtTunEn */ > - (1UL << 4) | /* iotblSup */ > - (1UL << 6) | /* PrefSup */ > - (1UL << 7), /* PPRSup */ > - 1); > - > /* > * A PCI bus walk, for each PCI host bridge, is necessary to create a > * complete set of IVHD entries. Do this into a separate blob so that we > @@ -2380,56 +2373,94 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, > build_append_int_noprefix(ivhd_blob, 0x0000001, 4); > } > > - ivhd_table_len += ivhd_blob->len; > - > /* > * When interrupt remapping is supported, we add a special IVHD device > - * for type IO-APIC. > - */ > - if (x86_iommu_ir_supported(x86_iommu_get_default())) { > - ivhd_table_len += 8; > - } > - > - /* IVHD length */ > - build_append_int_noprefix(table_data, ivhd_table_len, 2); > - /* DeviceID */ > - build_append_int_noprefix(table_data, > - object_property_get_int(OBJECT(&s->pci), "addr", > - &error_abort), 2); > - /* Capability offset */ > - build_append_int_noprefix(table_data, s->pci.capab_offset, 2); > - /* IOMMU base address */ > - build_append_int_noprefix(table_data, s->mmio.addr, 8); > - /* PCI Segment Group */ > - build_append_int_noprefix(table_data, 0, 2); > - /* IOMMU info */ > - build_append_int_noprefix(table_data, 0, 2); > - /* IOMMU Feature Reporting */ > - build_append_int_noprefix(table_data, > - (48UL << 30) | /* HATS */ > - (48UL << 28) | /* GATS */ > - (1UL << 2) | /* GTSup */ > - (1UL << 6), /* GASup */ > - 4); > - > - /* IVHD entries as found above */ > - g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len); > - g_array_free(ivhd_blob, TRUE); > - > - /* > - * Add a special IVHD device type. > + * for type IO-APIC > * Refer to spec - Table 95: IVHD device entry type codes > * > * Linux IOMMU driver checks for the special IVHD device (type IO-APIC). > * See Linux kernel commit 'c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059' > */ > if (x86_iommu_ir_supported(x86_iommu_get_default())) { > - build_append_int_noprefix(table_data, > + build_append_int_noprefix(ivhd_blob, > (0x1ull << 56) | /* type IOAPIC */ > (IOAPIC_SB_DEVID << 40) | /* IOAPIC devid */ > 0x48, /* special device */ > 8); > } > + > + /* IVHD definition - type 10h */ > + build_append_int_noprefix(table_data, 0x10, 1); > + /* virtualization flags */ > + build_append_int_noprefix(table_data, > + (1UL << 0) | /* HtTunEn */ > + (1UL << 4) | /* iotblSup */ > + (1UL << 6) | /* PrefSup */ > + (1UL << 7), /* PPRSup */ > + 1); > + > + /* IVHD length */ > + build_append_int_noprefix(table_data, ivhd_blob->len + 24, 2); > + /* DeviceID */ > + build_append_int_noprefix(table_data, > + object_property_get_int(OBJECT(&s->pci), "addr", > + &error_abort), 2); > + /* Capability offset */ > + build_append_int_noprefix(table_data, s->pci.capab_offset, 2); > + /* IOMMU base address */ > + build_append_int_noprefix(table_data, s->mmio.addr, 8); > + /* PCI Segment Group */ > + build_append_int_noprefix(table_data, 0, 2); > + /* IOMMU info */ > + build_append_int_noprefix(table_data, 0, 2); > + /* IOMMU Feature Reporting */ > + feature_report = (48UL << 30) | /* HATS */ > + (48UL << 28) | /* GATS */ > + (1UL << 2) | /* GTSup */ > + (1UL << 6); /* GASup */ > + if (s->xtsup) { > + feature_report |= (1UL << 0); /* XTSup */ > + } > + build_append_int_noprefix(table_data, feature_report, 4); > + > + /* IVHD entries as found above */ > + g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len); > + > + /* IVHD definition - type 11h */ > + build_append_int_noprefix(table_data, 0x11, 1); > + /* virtualization flags */ > + build_append_int_noprefix(table_data, > + (1UL << 0) | /* HtTunEn */ > + (1UL << 4), /* iotblSup */ > + 1); > + > + /* IVHD length */ > + build_append_int_noprefix(table_data, ivhd_blob->len + 40, 2); > + /* DeviceID */ > + build_append_int_noprefix(table_data, > + object_property_get_int(OBJECT(&s->pci), "addr", > + &error_abort), 2); > + /* Capability offset */ > + build_append_int_noprefix(table_data, s->pci.capab_offset, 2); > + /* IOMMU base address */ > + build_append_int_noprefix(table_data, s->mmio.addr, 8); > + /* PCI Segment Group */ > + build_append_int_noprefix(table_data, 0, 2); > + /* IOMMU info */ > + build_append_int_noprefix(table_data, 0, 2); > + /* IOMMU Attributes */ > + build_append_int_noprefix(table_data, 0, 4); > + /* EFR Register Image */ > + build_append_int_noprefix(table_data, > + amdvi_extended_feature_register(s), > + 8); > + /* EFR Register Image 2 */ > + build_append_int_noprefix(table_data, 0, 8); > + > + /* IVHD entries as found above */ > + g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len); > + > + g_array_free(ivhd_blob, TRUE); > acpi_table_end(linker, &table); > } > > diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c > index 7965415b47..e7809b641a 100644 > --- a/hw/i386/amd_iommu.c > +++ b/hw/i386/amd_iommu.c > @@ -31,6 +31,7 @@ > #include "hw/i386/apic_internal.h" > #include "trace.h" > #include "hw/i386/apic-msidef.h" > +#include "hw/qdev-properties.h" > > /* used AMD-Vi MMIO registers */ > const char *amdvi_mmio_low[] = { > @@ -74,6 +75,16 @@ typedef struct AMDVIIOTLBEntry { > uint64_t page_mask; /* physical page size */ > } AMDVIIOTLBEntry; > > +uint64_t amdvi_extended_feature_register(AMDVIState *s) > +{ > + uint64_t feature = AMDVI_DEFAULT_EXT_FEATURES; > + if (s->xtsup) { > + feature |= AMDVI_FEATURE_XT; > + } > + > + return feature; > +} > + > /* configure MMIO registers at startup/reset */ > static void amdvi_set_quad(AMDVIState *s, hwaddr addr, uint64_t val, > uint64_t romask, uint64_t w1cmask) > @@ -1155,7 +1166,12 @@ static int amdvi_int_remap_ga(AMDVIState *iommu, > irq->vector = irte.hi.fields.vector; > irq->dest_mode = irte.lo.fields_remap.dm; > irq->redir_hint = irte.lo.fields_remap.rq_eoi; > - irq->dest = irte.lo.fields_remap.destination; > + if (iommu->xtsup) { > + irq->dest = irte.lo.fields_remap.destination | > + (irte.hi.fields.destination_hi << 24); > + } else { > + irq->dest = irte.lo.fields_remap.destination & 0xff; > + } > > return 0; > } > @@ -1501,8 +1517,9 @@ static void amdvi_init(AMDVIState *s) > > /* reset MMIO */ > memset(s->mmior, 0, AMDVI_MMIO_SIZE); > - amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, AMDVI_EXT_FEATURES, > - 0xffffffffffffffef, 0); > + amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, > + amdvi_extended_feature_register(s), > + 0xffffffffffffffef, 0); > amdvi_set_quad(s, AMDVI_MMIO_STATUS, 0, 0x98, 0x67); > } > > @@ -1585,6 +1602,11 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp) > amdvi_init(s); > } > > +static Property amdvi_properties[] = { > + DEFINE_PROP_BOOL("xtsup", AMDVIState, xtsup, false), > + DEFINE_PROP_END_OF_LIST(), > +}; > + > static const VMStateDescription vmstate_amdvi_sysbus = { > .name = "amd-iommu", > .unmigratable = 1 > @@ -1611,6 +1633,7 @@ static void amdvi_sysbus_class_init(ObjectClass *klass, void *data) > dc->user_creatable = true; > set_bit(DEVICE_CATEGORY_MISC, dc->categories); > dc->desc = "AMD IOMMU (AMD-Vi) DMA Remapping device"; > + device_class_set_props(dc, amdvi_properties); > } > > static const TypeInfo amdvi_sysbus = { > diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h > index c5065a3e27..73619fe9ea 100644 > --- a/hw/i386/amd_iommu.h > +++ b/hw/i386/amd_iommu.h > @@ -154,6 +154,7 @@ > > #define AMDVI_FEATURE_PREFETCH (1ULL << 0) /* page prefetch */ > #define AMDVI_FEATURE_PPR (1ULL << 1) /* PPR Support */ > +#define AMDVI_FEATURE_XT (1ULL << 2) /* x2APIC Support */ > #define AMDVI_FEATURE_GT (1ULL << 4) /* Guest Translation */ > #define AMDVI_FEATURE_IA (1ULL << 6) /* inval all support */ > #define AMDVI_FEATURE_GA (1ULL << 7) /* guest VAPIC support */ > @@ -173,8 +174,9 @@ > #define AMDVI_IOTLB_MAX_SIZE 1024 > #define AMDVI_DEVID_SHIFT 36 > > -/* extended feature support */ > -#define AMDVI_EXT_FEATURES (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \ > +/* default extended feature */ > +#define AMDVI_DEFAULT_EXT_FEATURES \ > + (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \ > AMDVI_FEATURE_IA | AMDVI_FEATURE_GT | AMDVI_FEATURE_HE | \ > AMDVI_GATS_MODE | AMDVI_HATS_MODE | AMDVI_FEATURE_GA) > > @@ -276,8 +278,8 @@ union irte_ga_lo { > dm:1, > /* ------ */ > guest_mode:1, > - destination:8, > - rsvd_1:48; > + destination:24, > + rsvd_1:32; > } fields_remap; > }; > > @@ -285,7 +287,8 @@ union irte_ga_hi { > uint64_t val; > struct { > uint64_t vector:8, > - rsvd_2:56; > + rsvd_2:48, > + destination_hi:8; > } fields; > }; > > @@ -364,6 +367,9 @@ struct AMDVIState { > > /* Interrupt remapping */ > bool ga_enabled; > + bool xtsup; > }; > > +uint64_t amdvi_extended_feature_register(AMDVIState *s); > + > #endif > -- > 2.25.1
On 11/7/23 07:39, Michael S. Tsirkin wrote: > On Tue, Oct 24, 2023 at 10:21:05PM +0700, Bui Quang Minh wrote: >> This commit adds XTSup configuration to let user choose to whether enable >> this feature or not. When XTSup is enabled, additional bytes in IRTE with >> enabled guest virtual VAPIC are used to support 32-bit destination id. >> >> Additionally, this commit exports IVHD type 0x11 besides the old IVHD type >> 0x10 in ACPI table. IVHD type 0x10 does not report full set of IOMMU >> features only the legacy ones, so operating system (e.g. Linux) may only >> detects x2APIC support if IVHD type 0x11 is available. The IVHD type 0x10 >> is kept so that old operating system that only parses type 0x10 can detect >> the IOMMU device. >> >> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> >> Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com> > > > changes IVRS without updating expected files for tests. > result seems to be CI failures: > https://gitlab.com/mstredhat/qemu/-/jobs/5470533834 Thanks Michael, I am preparing the fix in the next version. I've read the instructions to update the test data in bios-tables-test.c. It says I need to create some separate patches to update the test data. Are there any reasons for this? I intend to change the binary and include the ASL diff into the commit message. Is it enough?
On Wed, Nov 08, 2023 at 09:22:18PM +0700, Bui Quang Minh wrote: > On 11/7/23 07:39, Michael S. Tsirkin wrote: > > On Tue, Oct 24, 2023 at 10:21:05PM +0700, Bui Quang Minh wrote: > > > This commit adds XTSup configuration to let user choose to whether enable > > > this feature or not. When XTSup is enabled, additional bytes in IRTE with > > > enabled guest virtual VAPIC are used to support 32-bit destination id. > > > > > > Additionally, this commit exports IVHD type 0x11 besides the old IVHD type > > > 0x10 in ACPI table. IVHD type 0x10 does not report full set of IOMMU > > > features only the legacy ones, so operating system (e.g. Linux) may only > > > detects x2APIC support if IVHD type 0x11 is available. The IVHD type 0x10 > > > is kept so that old operating system that only parses type 0x10 can detect > > > the IOMMU device. > > > > > > Reviewed-by: Michael S. Tsirkin <mst@redhat.com> > > > Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com> > > > > > > changes IVRS without updating expected files for tests. > > result seems to be CI failures: > > https://gitlab.com/mstredhat/qemu/-/jobs/5470533834 > > > Thanks Michael, I am preparing the fix in the next version. I've read the > instructions to update the test data in bios-tables-test.c. It says I need > to create some separate patches to update the test data. Are there any > reasons for this? I intend to change the binary and include the ASL diff > into the commit message. Is it enough? No, not enough. No, do not ignore the rules please. Yes, there's a reason. The reason is that I need to be able to rebase your patches. I then regenerate the binaries. If the patch includes binaries it won't rebase.
On 11/9/23 02:44, Michael S. Tsirkin wrote: > On Wed, Nov 08, 2023 at 09:22:18PM +0700, Bui Quang Minh wrote: >> On 11/7/23 07:39, Michael S. Tsirkin wrote: >>> On Tue, Oct 24, 2023 at 10:21:05PM +0700, Bui Quang Minh wrote: >>>> This commit adds XTSup configuration to let user choose to whether enable >>>> this feature or not. When XTSup is enabled, additional bytes in IRTE with >>>> enabled guest virtual VAPIC are used to support 32-bit destination id. >>>> >>>> Additionally, this commit exports IVHD type 0x11 besides the old IVHD type >>>> 0x10 in ACPI table. IVHD type 0x10 does not report full set of IOMMU >>>> features only the legacy ones, so operating system (e.g. Linux) may only >>>> detects x2APIC support if IVHD type 0x11 is available. The IVHD type 0x10 >>>> is kept so that old operating system that only parses type 0x10 can detect >>>> the IOMMU device. >>>> >>>> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> >>>> Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com> >>> >>> >>> changes IVRS without updating expected files for tests. >>> result seems to be CI failures: >>> https://gitlab.com/mstredhat/qemu/-/jobs/5470533834 >> >> >> Thanks Michael, I am preparing the fix in the next version. I've read the >> instructions to update the test data in bios-tables-test.c. It says I need >> to create some separate patches to update the test data. Are there any >> reasons for this? I intend to change the binary and include the ASL diff >> into the commit message. Is it enough? > > No, not enough. No, do not ignore the rules please. Yes, there's a > reason. The reason is that I need to be able to rebase your patches. I > then regenerate the binaries. If the patch includes binaries it won't > rebase. Okay, I got it. I will prepare the fix in the next version. Thanks, Quang Minh.
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 3f2b27cf75..8069971e54 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2337,30 +2337,23 @@ static void build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, const char *oem_table_id) { - int ivhd_table_len = 24; AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default()); GArray *ivhd_blob = g_array_new(false, true, 1); AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id, .oem_table_id = oem_table_id }; + uint64_t feature_report; acpi_table_begin(&table, table_data); /* IVinfo - IO virtualization information common to all * IOMMU units in a system */ - build_append_int_noprefix(table_data, 40UL << 8/* PASize */, 4); + build_append_int_noprefix(table_data, + (1UL << 0) | /* EFRSup */ + (40UL << 8), /* PASize */ + 4); /* reserved */ build_append_int_noprefix(table_data, 0, 8); - /* IVHD definition - type 10h */ - build_append_int_noprefix(table_data, 0x10, 1); - /* virtualization flags */ - build_append_int_noprefix(table_data, - (1UL << 0) | /* HtTunEn */ - (1UL << 4) | /* iotblSup */ - (1UL << 6) | /* PrefSup */ - (1UL << 7), /* PPRSup */ - 1); - /* * A PCI bus walk, for each PCI host bridge, is necessary to create a * complete set of IVHD entries. Do this into a separate blob so that we @@ -2380,56 +2373,94 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, build_append_int_noprefix(ivhd_blob, 0x0000001, 4); } - ivhd_table_len += ivhd_blob->len; - /* * When interrupt remapping is supported, we add a special IVHD device - * for type IO-APIC. - */ - if (x86_iommu_ir_supported(x86_iommu_get_default())) { - ivhd_table_len += 8; - } - - /* IVHD length */ - build_append_int_noprefix(table_data, ivhd_table_len, 2); - /* DeviceID */ - build_append_int_noprefix(table_data, - object_property_get_int(OBJECT(&s->pci), "addr", - &error_abort), 2); - /* Capability offset */ - build_append_int_noprefix(table_data, s->pci.capab_offset, 2); - /* IOMMU base address */ - build_append_int_noprefix(table_data, s->mmio.addr, 8); - /* PCI Segment Group */ - build_append_int_noprefix(table_data, 0, 2); - /* IOMMU info */ - build_append_int_noprefix(table_data, 0, 2); - /* IOMMU Feature Reporting */ - build_append_int_noprefix(table_data, - (48UL << 30) | /* HATS */ - (48UL << 28) | /* GATS */ - (1UL << 2) | /* GTSup */ - (1UL << 6), /* GASup */ - 4); - - /* IVHD entries as found above */ - g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len); - g_array_free(ivhd_blob, TRUE); - - /* - * Add a special IVHD device type. + * for type IO-APIC * Refer to spec - Table 95: IVHD device entry type codes * * Linux IOMMU driver checks for the special IVHD device (type IO-APIC). * See Linux kernel commit 'c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059' */ if (x86_iommu_ir_supported(x86_iommu_get_default())) { - build_append_int_noprefix(table_data, + build_append_int_noprefix(ivhd_blob, (0x1ull << 56) | /* type IOAPIC */ (IOAPIC_SB_DEVID << 40) | /* IOAPIC devid */ 0x48, /* special device */ 8); } + + /* IVHD definition - type 10h */ + build_append_int_noprefix(table_data, 0x10, 1); + /* virtualization flags */ + build_append_int_noprefix(table_data, + (1UL << 0) | /* HtTunEn */ + (1UL << 4) | /* iotblSup */ + (1UL << 6) | /* PrefSup */ + (1UL << 7), /* PPRSup */ + 1); + + /* IVHD length */ + build_append_int_noprefix(table_data, ivhd_blob->len + 24, 2); + /* DeviceID */ + build_append_int_noprefix(table_data, + object_property_get_int(OBJECT(&s->pci), "addr", + &error_abort), 2); + /* Capability offset */ + build_append_int_noprefix(table_data, s->pci.capab_offset, 2); + /* IOMMU base address */ + build_append_int_noprefix(table_data, s->mmio.addr, 8); + /* PCI Segment Group */ + build_append_int_noprefix(table_data, 0, 2); + /* IOMMU info */ + build_append_int_noprefix(table_data, 0, 2); + /* IOMMU Feature Reporting */ + feature_report = (48UL << 30) | /* HATS */ + (48UL << 28) | /* GATS */ + (1UL << 2) | /* GTSup */ + (1UL << 6); /* GASup */ + if (s->xtsup) { + feature_report |= (1UL << 0); /* XTSup */ + } + build_append_int_noprefix(table_data, feature_report, 4); + + /* IVHD entries as found above */ + g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len); + + /* IVHD definition - type 11h */ + build_append_int_noprefix(table_data, 0x11, 1); + /* virtualization flags */ + build_append_int_noprefix(table_data, + (1UL << 0) | /* HtTunEn */ + (1UL << 4), /* iotblSup */ + 1); + + /* IVHD length */ + build_append_int_noprefix(table_data, ivhd_blob->len + 40, 2); + /* DeviceID */ + build_append_int_noprefix(table_data, + object_property_get_int(OBJECT(&s->pci), "addr", + &error_abort), 2); + /* Capability offset */ + build_append_int_noprefix(table_data, s->pci.capab_offset, 2); + /* IOMMU base address */ + build_append_int_noprefix(table_data, s->mmio.addr, 8); + /* PCI Segment Group */ + build_append_int_noprefix(table_data, 0, 2); + /* IOMMU info */ + build_append_int_noprefix(table_data, 0, 2); + /* IOMMU Attributes */ + build_append_int_noprefix(table_data, 0, 4); + /* EFR Register Image */ + build_append_int_noprefix(table_data, + amdvi_extended_feature_register(s), + 8); + /* EFR Register Image 2 */ + build_append_int_noprefix(table_data, 0, 8); + + /* IVHD entries as found above */ + g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len); + + g_array_free(ivhd_blob, TRUE); acpi_table_end(linker, &table); } diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 7965415b47..e7809b641a 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -31,6 +31,7 @@ #include "hw/i386/apic_internal.h" #include "trace.h" #include "hw/i386/apic-msidef.h" +#include "hw/qdev-properties.h" /* used AMD-Vi MMIO registers */ const char *amdvi_mmio_low[] = { @@ -74,6 +75,16 @@ typedef struct AMDVIIOTLBEntry { uint64_t page_mask; /* physical page size */ } AMDVIIOTLBEntry; +uint64_t amdvi_extended_feature_register(AMDVIState *s) +{ + uint64_t feature = AMDVI_DEFAULT_EXT_FEATURES; + if (s->xtsup) { + feature |= AMDVI_FEATURE_XT; + } + + return feature; +} + /* configure MMIO registers at startup/reset */ static void amdvi_set_quad(AMDVIState *s, hwaddr addr, uint64_t val, uint64_t romask, uint64_t w1cmask) @@ -1155,7 +1166,12 @@ static int amdvi_int_remap_ga(AMDVIState *iommu, irq->vector = irte.hi.fields.vector; irq->dest_mode = irte.lo.fields_remap.dm; irq->redir_hint = irte.lo.fields_remap.rq_eoi; - irq->dest = irte.lo.fields_remap.destination; + if (iommu->xtsup) { + irq->dest = irte.lo.fields_remap.destination | + (irte.hi.fields.destination_hi << 24); + } else { + irq->dest = irte.lo.fields_remap.destination & 0xff; + } return 0; } @@ -1501,8 +1517,9 @@ static void amdvi_init(AMDVIState *s) /* reset MMIO */ memset(s->mmior, 0, AMDVI_MMIO_SIZE); - amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, AMDVI_EXT_FEATURES, - 0xffffffffffffffef, 0); + amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, + amdvi_extended_feature_register(s), + 0xffffffffffffffef, 0); amdvi_set_quad(s, AMDVI_MMIO_STATUS, 0, 0x98, 0x67); } @@ -1585,6 +1602,11 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp) amdvi_init(s); } +static Property amdvi_properties[] = { + DEFINE_PROP_BOOL("xtsup", AMDVIState, xtsup, false), + DEFINE_PROP_END_OF_LIST(), +}; + static const VMStateDescription vmstate_amdvi_sysbus = { .name = "amd-iommu", .unmigratable = 1 @@ -1611,6 +1633,7 @@ static void amdvi_sysbus_class_init(ObjectClass *klass, void *data) dc->user_creatable = true; set_bit(DEVICE_CATEGORY_MISC, dc->categories); dc->desc = "AMD IOMMU (AMD-Vi) DMA Remapping device"; + device_class_set_props(dc, amdvi_properties); } static const TypeInfo amdvi_sysbus = { diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h index c5065a3e27..73619fe9ea 100644 --- a/hw/i386/amd_iommu.h +++ b/hw/i386/amd_iommu.h @@ -154,6 +154,7 @@ #define AMDVI_FEATURE_PREFETCH (1ULL << 0) /* page prefetch */ #define AMDVI_FEATURE_PPR (1ULL << 1) /* PPR Support */ +#define AMDVI_FEATURE_XT (1ULL << 2) /* x2APIC Support */ #define AMDVI_FEATURE_GT (1ULL << 4) /* Guest Translation */ #define AMDVI_FEATURE_IA (1ULL << 6) /* inval all support */ #define AMDVI_FEATURE_GA (1ULL << 7) /* guest VAPIC support */ @@ -173,8 +174,9 @@ #define AMDVI_IOTLB_MAX_SIZE 1024 #define AMDVI_DEVID_SHIFT 36 -/* extended feature support */ -#define AMDVI_EXT_FEATURES (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \ +/* default extended feature */ +#define AMDVI_DEFAULT_EXT_FEATURES \ + (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \ AMDVI_FEATURE_IA | AMDVI_FEATURE_GT | AMDVI_FEATURE_HE | \ AMDVI_GATS_MODE | AMDVI_HATS_MODE | AMDVI_FEATURE_GA) @@ -276,8 +278,8 @@ union irte_ga_lo { dm:1, /* ------ */ guest_mode:1, - destination:8, - rsvd_1:48; + destination:24, + rsvd_1:32; } fields_remap; }; @@ -285,7 +287,8 @@ union irte_ga_hi { uint64_t val; struct { uint64_t vector:8, - rsvd_2:56; + rsvd_2:48, + destination_hi:8; } fields; }; @@ -364,6 +367,9 @@ struct AMDVIState { /* Interrupt remapping */ bool ga_enabled; + bool xtsup; }; +uint64_t amdvi_extended_feature_register(AMDVIState *s); + #endif