Mailing List Archive

[PATCH 11 of 14 V3] hvmloader: Build IVRS table
# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1326213614 -3600
# Node ID 01d2c1d4e3b992997f170d95dccc2195b9206b04
# Parent f1bf84f5fbb94f8702c8e96462e715ad5066dca2
hvmloader: Build IVRS table.
Signed-off-by: Wei Wang <wei.wang2@amd.com>

diff -r f1bf84f5fbb9 -r 01d2c1d4e3b9 tools/firmware/hvmloader/acpi/acpi2_0.h
--- a/tools/firmware/hvmloader/acpi/acpi2_0.h Tue Jan 10 17:40:11 2012 +0100
+++ b/tools/firmware/hvmloader/acpi/acpi2_0.h Tue Jan 10 17:40:14 2012 +0100
@@ -389,6 +389,60 @@ struct acpi_20_madt_intsrcovr {
#define ACPI_2_0_WAET_REVISION 0x01
#define ACPI_1_0_FADT_REVISION 0x01

+#define IVRS_SIGNATURE ASCII32('I','V','R','S')
+#define IVRS_REVISION 1
+#define IVRS_VASIZE 64
+#define IVRS_PASIZE 52
+#define IVRS_GVASIZE 64
+
+#define IVHD_BLOCK_TYPE 0x10
+#define IVHD_FLAG_HTTUNEN (1 << 0)
+#define IVHD_FLAG_PASSPW (1 << 1)
+#define IVHD_FLAG_RESPASSPW (1 << 2)
+#define IVHD_FLAG_ISOC (1 << 3)
+#define IVHD_FLAG_IOTLBSUP (1 << 4)
+#define IVHD_FLAG_COHERENT (1 << 5)
+#define IVHD_FLAG_PREFSUP (1 << 6)
+#define IVHD_FLAG_PPRSUP (1 << 7)
+
+#define IVHD_EFR_GTSUP (1 << 2)
+#define IVHD_EFR_IASUP (1 << 5)
+
+#define IVHD_SELECT_4_BYTE 0x2
+
+struct ivrs_ivhd_block
+{
+ uint8_t type;
+ uint8_t flags;
+ uint16_t length;
+ uint16_t devid;
+ uint16_t cap_offset;
+ uint64_t iommu_base_addr;
+ uint16_t pci_segment;
+ uint16_t iommu_info;
+ uint32_t reserved;
+};
+
+/* IVHD 4-byte device entries */
+struct ivrs_ivhd_device
+{
+ uint8_t type;
+ uint16_t dev_id;
+ uint8_t flags;
+};
+
+#define PT_DEV_MAX_NR 32
+#define IOMMU_CAP_OFFSET 0x40
+struct acpi_40_ivrs
+{
+ struct acpi_header header;
+ uint32_t iv_info;
+ uint32_t reserved[2];
+ struct ivrs_ivhd_block ivhd_block;
+ struct ivrs_ivhd_device ivhd_device[PT_DEV_MAX_NR];
+};
+
+
#pragma pack ()

struct acpi_config {
diff -r f1bf84f5fbb9 -r 01d2c1d4e3b9 tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c Tue Jan 10 17:40:11 2012 +0100
+++ b/tools/firmware/hvmloader/acpi/build.c Tue Jan 10 17:40:14 2012 +0100
@@ -23,6 +23,8 @@
#include "ssdt_pm.h"
#include "../config.h"
#include "../util.h"
+#include "../hypercall.h"
+#include <xen/hvm/params.h>

#define align16(sz) (((sz) + 15) & ~15)
#define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
@@ -198,6 +200,77 @@ static struct acpi_20_waet *construct_wa
return waet;
}

+extern uint32_t ptdev_bdf[PT_DEV_MAX_NR];
+extern uint32_t ptdev_nr;
+extern uint32_t iommu_bdf;
+static struct acpi_40_ivrs* construct_ivrs(void)
+{
+ struct acpi_40_ivrs *ivrs;
+ uint64_t mmio;
+ struct ivrs_ivhd_block *ivhd;
+ struct ivrs_ivhd_device *dev_entry;
+ struct xen_hvm_param p;
+
+ if (ptdev_nr == 0) return NULL;
+
+ ivrs = mem_alloc(sizeof(*ivrs), 16);
+ if (!ivrs) return NULL;
+
+ memset(ivrs, 0, sizeof(*ivrs));
+
+ /* initialize acpi header */
+ ivrs->header.signature = IVRS_SIGNATURE;
+ ivrs->header.revision = IVRS_REVISION;
+ fixed_strcpy(ivrs->header.oem_id, ACPI_OEM_ID);
+ fixed_strcpy(ivrs->header.oem_table_id, ACPI_OEM_TABLE_ID);
+
+ ivrs->header.oem_revision = ACPI_OEM_REVISION;
+ ivrs->header.creator_id = ACPI_CREATOR_ID;
+ ivrs->header.creator_revision = ACPI_CREATOR_REVISION;
+
+ ivrs->header.length = sizeof(*ivrs);
+
+ /* initialize IVHD Block */
+ ivhd = &ivrs->ivhd_block;
+ ivrs->iv_info = (IVRS_VASIZE << 15) | (IVRS_PASIZE << 8) |
+ (IVRS_GVASIZE << 5);
+
+ ivhd->type = IVHD_BLOCK_TYPE;
+ ivhd->flags = IVHD_FLAG_PPRSUP | IVHD_FLAG_IOTLBSUP;
+ ivhd->devid = iommu_bdf;
+ ivhd->cap_offset = IOMMU_CAP_OFFSET;
+
+ /*reserve 32K IOMMU MMIO space */
+ mmio = virt_to_phys(mem_alloc(0x8000, 0x1000));
+ if (!mmio) return NULL;
+
+ p.domid = DOMID_SELF;
+ p.index = HVM_PARAM_IOMMU_BASE;
+ p.value = mmio;
+
+ /* Return non-zero if IOMMUv2 hardware is not avaliable */
+ if ( hypercall_hvm_op(HVMOP_set_param, &p) )
+ return NULL;
+
+ ivhd->iommu_base_addr = mmio;
+ ivhd->reserved = IVHD_EFR_IASUP | IVHD_EFR_GTSUP;
+
+ /* Build IVHD device entries */
+ dev_entry = ivrs->ivhd_device;
+ for ( int i = 0; i < ptdev_nr; i++ )
+ {
+ dev_entry[i].type = IVHD_SELECT_4_BYTE;
+ dev_entry[i].dev_id = ptdev_bdf[i];
+ dev_entry[i].flags = 0;
+ }
+
+ ivhd->length = sizeof(*ivhd) + sizeof(*dev_entry) * PT_DEV_MAX_NR;
+ set_checksum(ivrs, offsetof(struct acpi_header, checksum),
+ ivrs->header.length);
+
+ return ivrs;
+}
+
static int construct_secondary_tables(unsigned long *table_ptrs,
struct acpi_info *info)
{
@@ -206,6 +279,7 @@ static int construct_secondary_tables(un
struct acpi_20_hpet *hpet;
struct acpi_20_waet *waet;
struct acpi_20_tcpa *tcpa;
+ struct acpi_40_ivrs *ivrs;
unsigned char *ssdt;
static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
uint16_t *tis_hdr;
@@ -293,6 +367,13 @@ static int construct_secondary_tables(un
}
}

+ if ( !strncmp(xenstore_read("iommu", "1"), "1", 1) )
+ {
+ ivrs = construct_ivrs();
+ if ( ivrs != NULL )
+ table_ptrs[nr_tables++] = (unsigned long)ivrs;
+ }
+
table_ptrs[nr_tables] = 0;
return nr_tables;
}
diff -r f1bf84f5fbb9 -r 01d2c1d4e3b9 tools/firmware/hvmloader/pci.c
--- a/tools/firmware/hvmloader/pci.c Tue Jan 10 17:40:11 2012 +0100
+++ b/tools/firmware/hvmloader/pci.c Tue Jan 10 17:40:14 2012 +0100
@@ -34,11 +34,17 @@ unsigned long pci_mem_end = PCI_MEM_END;
enum virtual_vga virtual_vga = VGA_none;
unsigned long igd_opregion_pgbase = 0;

+/* support up to 32 passthrough devices */
+#define PT_DEV_MAX_NR 32
+uint32_t ptdev_bdf[PT_DEV_MAX_NR];
+uint32_t ptdev_nr;
+uint32_t iommu_bdf;
+
void pci_setup(void)
{
uint32_t base, devfn, bar_reg, bar_data, bar_sz, cmd, mmio_total = 0;
uint32_t vga_devfn = 256;
- uint16_t class, vendor_id, device_id;
+ uint16_t class, vendor_id, device_id, sub_vendor_id;
unsigned int bar, pin, link, isa_irq;

/* Resources assignable to PCI devices via BARs. */
@@ -72,12 +78,34 @@ void pci_setup(void)
class = pci_readw(devfn, PCI_CLASS_DEVICE);
vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
device_id = pci_readw(devfn, PCI_DEVICE_ID);
+ sub_vendor_id = pci_readw(devfn, PCI_SUBSYSTEM_VENDOR_ID);
+
if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
continue;

ASSERT((devfn != PCI_ISA_DEVFN) ||
((vendor_id == 0x8086) && (device_id == 0x7000)));

+ /* Found amd iommu device. */
+ if ( class == 0x0806 && vendor_id == 0x1022 )
+ {
+ iommu_bdf = devfn;
+ continue;
+ }
+ /* IVRS: Detecting passthrough devices.
+ * sub_vendor_id != citrix && sub_vendor_id != qemu */
+ if ( sub_vendor_id != 0x5853 && sub_vendor_id != 0x1af4 )
+ {
+ /* found amd iommu device */
+ if ( ptdev_nr < PT_DEV_MAX_NR )
+ {
+ ptdev_bdf[ptdev_nr] = devfn;
+ ptdev_nr++;
+ }
+ else
+ printf("Number of passthru devices > PT_DEV_MAX_NR \n");
+ }
+
switch ( class )
{
case 0x0300:


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel