diff mbox

apb: add IOMMU flush register implementation

Message ID 1407756172-16444-1-git-send-email-mark.cave-ayland@ilande.co.uk
State New
Headers show

Commit Message

Mark Cave-Ayland Aug. 11, 2014, 11:22 a.m. UTC
The IOMMU flush register is a write-only register used to remove entries from the
hardware TLB. Allow guest writes to this register as a no-op, and return a value
of 0 for reads.

This fixes IOMMU DMA operations under NetBSD SPARC64.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
 hw/pci-host/apb.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index d238a84..60bd81e 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -94,6 +94,7 @@  do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
 #define IOMMU_CTRL_TSB_SHIFT    16
 
 #define IOMMU_BASE              0x8
+#define IOMMU_FLUSH             0x10
 
 #define IOMMU_TTE_DATA_V        (1ULL << 63)
 #define IOMMU_TTE_DATA_SIZE     (1ULL << 61)
@@ -352,6 +353,9 @@  static void iommu_config_write(void *opaque, hwaddr addr,
         is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL;
         is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL;
         break;
+    case IOMMU_FLUSH:
+    case IOMMU_FLUSH + 0x4:
+        break;
     default:
         qemu_log_mask(LOG_UNIMP,
                   "apb iommu: Unimplemented register write "
@@ -387,6 +391,10 @@  static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size)
     case IOMMU_BASE + 0x4:
         val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL;
         break;
+    case IOMMU_FLUSH:
+    case IOMMU_FLUSH + 0x4:
+        val = 0;
+        break;
     default:
         qemu_log_mask(LOG_UNIMP,
                       "apb iommu: Unimplemented register read "
@@ -415,7 +423,7 @@  static void apb_config_writel (void *opaque, hwaddr addr,
         /* XXX: not implemented yet */
         break;
     case 0x200 ... 0x217: /* IOMMU */
-        iommu_config_write(is, (addr & 0xf), val, size);
+        iommu_config_write(is, (addr & 0x1f), val, size);
         break;
     case 0xc00 ... 0xc3f: /* PCI interrupt control */
         if (addr & 4) {
@@ -497,7 +505,7 @@  static uint64_t apb_config_readl (void *opaque,
         /* XXX: not implemented yet */
         break;
     case 0x200 ... 0x217: /* IOMMU */
-        val = iommu_config_read(is, (addr & 0xf), size);
+        val = iommu_config_read(is, (addr & 0x1f), size);
         break;
     case 0xc00 ... 0xc3f: /* PCI interrupt control */
         if (addr & 4) {