]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
core/configs/tools: Report IOMMU association of devices via config file
authorJan Kiszka <jan.kiszka@siemens.com>
Wed, 20 Aug 2014 07:08:01 +0000 (09:08 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Thu, 28 Aug 2014 06:33:07 +0000 (08:33 +0200)
We will need this information for emulating VT-d for the root cell:

Add an iommu field to the PCI device config structure and encode the
unit number in the id field of the IOAPIC's irqchip structure.
The config generator fills the fields according to the DMAR ACPI table.
However, we do not yet understand all exotic forms of Device Scope
structures.

If it turns out that there are PCI devices without any IOMMU
association, refuse to generate a config file - such systems are
unsupported (with the temporary exception of AMD platforms).

Update the h87i config accordingly. QEMU currently only exposes a single
DMAR unit, thus the implicit zero-initialization is fine. As the IOMMU
number is only used in the context of the root cell, ioapic-demo and
pci-demo require no updates as well.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
configs/h87i.c
configs/ioapic-demo.c
hypervisor/arch/x86/include/asm/cell.h
hypervisor/arch/x86/ioapic.c
hypervisor/include/jailhouse/cell-config.h
tools/jailhouse-config-create
tools/root-cell-config.c.tmpl

index 2b74999fee95e0b89c9948ee19ab7b8f67ba28af..27fcc2f8d4cd4cc0906fe03d60dbe7ffb7f214ca 100644 (file)
@@ -117,7 +117,7 @@ struct {
        .irqchips = {
                /* IOAPIC */ {
                        .address = 0xfec00000,
-                       .id = 0xf0f8,
+                       .id = 0x1f0f8,
                        .pin_bitmap = 0xffffff,
                },
        },
@@ -139,6 +139,7 @@ struct {
                /* PCIDevice: 00:00.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0x0,
                        .caps_start = 0,
@@ -147,6 +148,7 @@ struct {
                /* PCIDevice: 00:01.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_BRIDGE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0x8,
                        .caps_start = 1,
@@ -156,6 +158,7 @@ struct {
                /* PCIDevice: 00:02.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 0,
                        .domain = 0x0,
                        .bdf = 0x10,
                        .caps_start = 5,
@@ -165,6 +168,7 @@ struct {
                /* PCIDevice: 00:03.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0x18,
                        .caps_start = 8,
@@ -174,6 +178,7 @@ struct {
                /* PCIDevice: 00:14.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xa0,
                        .caps_start = 11,
@@ -184,6 +189,7 @@ struct {
                /* PCIDevice: 00:16.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xb0,
                        .caps_start = 13,
@@ -194,6 +200,7 @@ struct {
                /* PCIDevice: 00:19.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xc8,
                        .caps_start = 15,
@@ -204,6 +211,7 @@ struct {
                /* PCIDevice: 00:1a.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xd0,
                        .caps_start = 18,
@@ -212,6 +220,7 @@ struct {
                /* PCIDevice: 00:1b.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xd8,
                        .caps_start = 21,
@@ -222,6 +231,7 @@ struct {
                /* PCIDevice: 00:1d.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xe8,
                        .caps_start = 18,
@@ -230,6 +240,7 @@ struct {
                /* PCIDevice: 00:1f.0 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xf8,
                        .caps_start = 0,
@@ -238,6 +249,7 @@ struct {
                /* PCIDevice: 00:1f.2 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xfa,
                        .caps_start = 24,
@@ -247,6 +259,7 @@ struct {
                /* PCIDevice: 00:1f.3 */
                {
                        .type = JAILHOUSE_PCI_TYPE_DEVICE,
+                       .iommu = 1,
                        .domain = 0x0,
                        .bdf = 0xfb,
                        .caps_start = 0,
index 35f534f4cbdc5a50a92154814e7415b4141bde1e..1a4315ed48b3d6010de28ac0f0c5f9e2a0289909 100644 (file)
@@ -59,6 +59,7 @@ struct {
        .irqchips = {
                /* IOAPIC */ {
                        .address = 0xfec00000,
+                       .id = 0xff01,
                        .pin_bitmap = 0x000200, /* ACPI IRQ */
                },
        },
index ba18d70673f550c4d02c266120d6dece25138c3f..70afb256ce199ab5ce6c369f889f04af5d75c76c 100644 (file)
@@ -55,6 +55,7 @@ struct cell {
 
        u32 ioapic_index_reg_val;
        u16 ioapic_id;
+       u8 ioapic_iommu;
        u64 ioapic_pin_bitmap;
 
        union {
index acd179cfa59f3f208f65b904bff9f2e5b87a0233..a0b77dd0808e54e2354fe6ba92258f3caebc90d1 100644 (file)
@@ -212,7 +212,8 @@ void ioapic_cell_init(struct cell *cell)
                ioapic_find_config(cell->config);
 
        if (irqchip) {
-               cell->ioapic_id = irqchip->id;
+               cell->ioapic_id = (u16)irqchip->id;
+               cell->ioapic_iommu = (u8)(irqchip->id >> 16);
                cell->ioapic_pin_bitmap = irqchip->pin_bitmap;
 
                if (cell != &root_cell) {
index b01d6b5dfbc9e09f12e77d67b8b0ce4c92f12bbc..d0b034107fa642c350eb4c453954f3c0314bcf8e 100644 (file)
@@ -60,7 +60,8 @@ struct jailhouse_irqchip {
 #define JAILHOUSE_PCI_TYPE_BRIDGE      0x02
 
 struct jailhouse_pci_device {
-       __u16 type;
+       __u8 type;
+       __u8 iommu;
        __u16 domain;
        __u16 bdf;
        __u16 caps_start;
index 6474534823774bd413ebaa1525630da402ae8909..7aedd5c5427298b74d95635028063159cae653b1 100755 (executable)
@@ -184,6 +184,7 @@ class PCICapability:
 class PCIDevice:
     def __init__(self, type, domain, bus, dev, fn, caps):
         self.type = type
+        self.iommu = None
         self.domain = domain
         self.bus = bus
         self.dev = dev
@@ -473,7 +474,7 @@ def parse_dmar_devscope(f):
 
 # parsing of DMAR ACPI Table
 # see Intel VT-d Spec chapter 8
-def parse_dmar():
+def parse_dmar(pcidevices):
     f = input_open('/sys/firmware/acpi/tables/DMAR', 'rb', True)
     if get_cpu_vendor() == 'AuthenticAMD':
         print('WARNING: AMD IOMMU support is not implemented yet')
@@ -498,22 +499,34 @@ def parse_dmar():
 
         # DMA Remapping Hardware Unit Definition
         if struct_type == 0:
-            (segment, base) = struct.unpack('<xxHQ', f.read(12))
+            (flags, segment, base) = struct.unpack('<BxHQ', f.read(12))
             if segment != 0:
                 raise RuntimeError('We do not support multiple PCI segments')
             if len(units) >= 8:
                 raise RuntimeError('Too many DMAR units. '
                                    'Raise JAILHOUSE_MAX_DMAR_UNITS.')
             units.append(base)
+            if flags & 1:
+                for d in pcidevices:
+                    if d.iommu == None:
+                        d.iommu = len(units) - 1
             offset += 16 - offset
             while offset < struct_len:
                 (scope_type, scope_len, bus, dev, fn) =\
                     parse_dmar_devscope(f)
-                if scope_type == 3:
+                if scope_type == 1:
+                    for d in pcidevices:
+                        if d.bus == bus and d.dev == dev and d.fn == fn:
+                            d.iommu = len(units) - 1
+                elif scope_type == 2:
+                    raise RuntimeError('Unsupported DMAR Device Scope type')
+                elif scope_type == 3:
                     if ioapic_id != 0:
                         raise RuntimeError('We do not support more '
                                            'than 1 IOAPIC')
-                    ioapic_id = (bus << 8) | (dev << 3) | fn
+                    # encode the DMAR unit number into the device ID
+                    ioapic_id = ((len(units) - 1) << 16) | \
+                        (bus << 8) | (dev << 3) | fn
                 offset += scope_len
 
         # Reserved Memory Region Reporting Structure
@@ -613,9 +626,16 @@ total = hvmem[1] + inmatemem
 
 mmconfig = MMConfig.parse()
 
-(dmar_units, ioapic_id, rmrr_regs) = parse_dmar()
+(dmar_units, ioapic_id, rmrr_regs) = parse_dmar(pcidevices)
 regions += rmrr_regs
 
+for d in pcidevices:
+    if get_cpu_vendor() == 'AuthenticAMD':
+        d.iommu = 0  # temporary workaround
+    if d.iommu == None:
+        raise RuntimeError('PCI device %02x:%02x.%x outside the scope of an '
+                           'IOMMU' % (d.bus, d.dev, d.fn))
+
 # kernel does not have memmap region, pick one
 if ourmem is None:
     ourmem = alloc_mem(regions, total)
index fb34462f11dffa26fcce3a33839fc3d4cefc776a..f111dbbb609bc8e24b060995e637860c2afd7750 100644 (file)
@@ -107,6 +107,7 @@ struct {
                /* ${str(d)} */
                {
                        .type = ${d.type},
+                       .iommu = ${d.iommu},
                        .domain = ${hex(d.domain)},
                        .bdf = ${hex(d.bdf())},
                        .caps_start = ${d.caps_start},