LWN.net Logo

[PATCH v2 7/7] i440fx: add an iommu

From:  Avi Kivity <avi-AT-redhat.com>
To:  qemu-devel-AT-nongnu.org
Subject:  [PATCH v2 7/7] i440fx: add an iommu
Date:  Tue, 30 Oct 2012 13:47:50 +0200
Message-ID:  <1351597670-23031-8-git-send-email-avi@redhat.com>
Cc:  "Michael S. Tsirkin" <mst-AT-redhat.com>, Alexander Graf <agraf-AT-suse.de>, Blue Swirl <blauwirbel-AT-gmail.com>, Alex Williamson <alex.williamson-AT-redhat.com>, Anthony Liguori <anthony-AT-codemonkey.ws>
Archive-link:  Article, Thread

This iommu encrypts addresses on the device bus to avoid divuling information
to hackers equipped with bus analyzers.  Following 3DES, addresses are encrypted
multiple times.  A XOR cypher is employed for efficiency.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/piix_pci.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 9af5847..99601f4 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -30,6 +30,7 @@
 #include "sysbus.h"
 #include "range.h"
 #include "xen.h"
+#include "exec-memory.h"
 
 /*
  * I440FX chipset data sheet.
@@ -248,6 +249,81 @@ static int i440fx_initfn(PCIDevice *dev)
     return 0;
 }
 
+typedef struct SillyIOMMU SillyIOMMU;
+
+struct SillyIOMMU {
+    MemoryRegion fault;
+    MemoryRegion l1;
+    MemoryRegion l2;
+    hwaddr mask;
+    hwaddr secret;
+};
+
+static IOMMUTLBEntry silly_l1_translate(MemoryRegion *l1, hwaddr addr)
+{
+    SillyIOMMU *s = container_of(l1, SillyIOMMU, l1);
+    hwaddr xlat = addr ^ s->secret;
+
+    printf("l1: %" HWADDR_PRIx " -> %" HWADDR_PRIx "\n", addr, xlat);
+
+    return (IOMMUTLBEntry) {
+        .device_addr = addr & ~s->mask,
+        .translated_addr = xlat & ~s->mask,
+        .addr_mask = s->mask,
+        .perm = { true, true },
+    };
+}
+
+static MemoryRegionIOMMUOps silly_l1_iommu_ops = {
+    .translate = silly_l1_translate,
+};
+
+static IOMMUTLBEntry silly_l2_translate(MemoryRegion *l2, hwaddr addr)
+{
+    SillyIOMMU *s = container_of(l2, SillyIOMMU, l2);
+    hwaddr xlat = addr ^ s->secret;
+
+    printf("l2: %" HWADDR_PRIx " -> %" HWADDR_PRIx "\n", addr, xlat);
+
+    return (IOMMUTLBEntry) {
+        .device_addr = addr & ~s->mask,
+        .translated_addr = xlat & ~s->mask,
+        .addr_mask = s->mask,
+        .perm = { true, true },
+    };
+}
+
+static MemoryRegionIOMMUOps silly_l2_iommu_ops = {
+    .translate = silly_l2_translate,
+};
+
+static MemoryRegion *silly_iommu_new(PCIBus *bus, void *opaque, int devfn)
+{
+    SillyIOMMU *s = g_new(SillyIOMMU, 1);
+    MemoryRegion *sysmem = get_system_memory();
+
+    s->mask = (0x1000 << (devfn >> 3)) - 1;
+    s->secret = ((devfn << 24) | 0x00aabbccdd) & ~s->mask;
+    memory_region_init(&s->fault, "silly-fault", INT64_MAX);
+    memory_region_init_iommu(&s->l2, &silly_l2_iommu_ops, sysmem, &s->fault,
+                             "silly-l2", INT64_MAX);
+    memory_region_init_iommu(&s->l1, &silly_l1_iommu_ops, &s->l2, &s->fault,
+                             "silly-l1", INT64_MAX);
+    return &s->l1;
+}
+
+static void silly_iommu_del(MemoryRegion *l1)
+{
+    SillyIOMMU *s = container_of(l1, SillyIOMMU, l1);
+
+    memory_region_del_subregion(&s->l2, get_system_memory());
+    memory_region_del_subregion(&s->l1, &s->l2);
+    memory_region_destroy(&s->l2);
+    memory_region_destroy(&s->l1);
+    memory_region_destroy(&s->fault);
+    g_free(s);
+}
+
 static PCIBus *i440fx_common_init(const char *device_name,
                                   PCII440FXState **pi440fx_state,
                                   int *piix3_devfn,
@@ -275,6 +351,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
     s->address_space = address_space_mem;
     b = pci_bus_new(dev, NULL, pci_address_space,
                     address_space_io, 0);
+    pci_setup_iommu(b, silly_iommu_new, silly_iommu_del, NULL);
     s->bus = b;
     object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
-- 
1.7.12





(Log in to post comments)

[PATCH v2 7/7] i440fx: add an iommu

Posted Nov 2, 2012 0:15 UTC (Fri) by vonbrand (subscriber, #4458) [Link]

Several rounds of XOR are equivalent to one round of XOR... get two messages XORed to the same key, you have the XOR of the messages. Know some bits of the message, you get the bits of the key.

[PATCH v2 7/7] i440fx: add an iommu

Posted Nov 2, 2012 4:23 UTC (Fri) by mjg59 (subscriber, #23239) [Link]

You may have discovered the joke.

[PATCH v2 7/7] i440fx: add an iommu

Posted Nov 2, 2012 20:05 UTC (Fri) by jonabbey (subscriber, #2736) [Link]

By george, I think he's got it! ;-p

[PATCH v2 7/7] i440fx: add an iommu

Posted Nov 5, 2012 15:26 UTC (Mon) by ortalo (subscriber, #4654) [Link]

Don't laugh so loudly, that's an attempt at a variant of Shannon's perfect cipher after all. Hey, not everyone can afford an infinite key length!
Okay, while we are on savings, we could equivalently save the XOR step and not do any enc^D^D^D scrambling at all for an even cheaper, faster and nearly as (un)secure variant...

Copyright © 2012, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds