summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/block/nvme.c39
-rw-r--r--hw/block/nvme.h1
-rw-r--r--hw/core/Makefile.objs5
-rw-r--r--hw/core/qdev-fw.c96
-rw-r--r--hw/core/qdev.c77
-rw-r--r--hw/display/vga.c3
-rw-r--r--hw/s390x/s390-stattrib-kvm.c4
-rw-r--r--hw/s390x/sclp.c6
-rw-r--r--hw/s390x/virtio-ccw.c5
-rw-r--r--hw/virtio/virtio-bus.c19
-rw-r--r--hw/virtio/virtio.c5
-rw-r--r--hw/xtensa/Makefile.objs1
-rw-r--r--hw/xtensa/sim.c38
-rw-r--r--hw/xtensa/xtensa_memory.c55
-rw-r--r--hw/xtensa/xtensa_memory.h40
-rw-r--r--hw/xtensa/xtfpga.c414
16 files changed, 564 insertions, 244 deletions
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 1ac356d3a5..51a58fefba 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -91,7 +91,19 @@ static uint8_t nvme_sq_empty(NvmeSQueue *sq)
     return sq->head == sq->tail;
 }
 
-static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
+static void nvme_irq_check(NvmeCtrl *n)
+{
+    if (msix_enabled(&(n->parent_obj))) {
+        return;
+    }
+    if (~n->bar.intms & n->irq_status) {
+        pci_irq_assert(&n->parent_obj);
+    } else {
+        pci_irq_deassert(&n->parent_obj);
+    }
+}
+
+static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq)
 {
     if (cq->irq_enabled) {
         if (msix_enabled(&(n->parent_obj))) {
@@ -99,13 +111,28 @@ static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
             msix_notify(&(n->parent_obj), cq->vector);
         } else {
             trace_nvme_irq_pin();
-            pci_irq_pulse(&n->parent_obj);
+            assert(cq->cqid < 64);
+            n->irq_status |= 1 << cq->cqid;
+            nvme_irq_check(n);
         }
     } else {
         trace_nvme_irq_masked();
     }
 }
 
+static void nvme_irq_deassert(NvmeCtrl *n, NvmeCQueue *cq)
+{
+    if (cq->irq_enabled) {
+        if (msix_enabled(&(n->parent_obj))) {
+            return;
+        } else {
+            assert(cq->cqid < 64);
+            n->irq_status &= ~(1 << cq->cqid);
+            nvme_irq_check(n);
+        }
+    }
+}
+
 static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
                              uint64_t prp2, uint32_t len, NvmeCtrl *n)
 {
@@ -242,7 +269,7 @@ static void nvme_post_cqes(void *opaque)
             sizeof(req->cqe));
         QTAILQ_INSERT_TAIL(&sq->req_list, req, entry);
     }
-    nvme_isr_notify(n, cq);
+    nvme_irq_assert(n, cq);
 }
 
 static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req)
@@ -905,6 +932,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
         n->bar.intmc = n->bar.intms;
         trace_nvme_mmio_intm_set(data & 0xffffffff,
                                  n->bar.intmc);
+        nvme_irq_check(n);
         break;
     case 0x10:  /* INTMC */
         if (unlikely(msix_enabled(&(n->parent_obj)))) {
@@ -917,6 +945,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
         n->bar.intmc = n->bar.intms;
         trace_nvme_mmio_intm_clr(data & 0xffffffff,
                                  n->bar.intmc);
+        nvme_irq_check(n);
         break;
     case 0x14:  /* CC */
         trace_nvme_mmio_cfg(data & 0xffffffff);
@@ -1085,8 +1114,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
             timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
         }
 
-        if (cq->tail != cq->head) {
-            nvme_isr_notify(n, cq);
+        if (cq->tail == cq->head) {
+            nvme_irq_deassert(n, cq);
         }
     } else {
         /* Submission queue doorbell write */
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index 6aab338ff5..7b62dad072 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -775,6 +775,7 @@ typedef struct NvmeCtrl {
     uint32_t    cmbsz;
     uint32_t    cmbloc;
     uint8_t     *cmbuf;
+    uint64_t    irq_status;
 
     char            *serial;
     NvmeNamespace   *namespaces;
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index f8d7a4aaed..1240728c87 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -1,11 +1,12 @@
 # core qdev-related obj files, also used by *-user:
 common-obj-y += qdev.o qdev-properties.o
 common-obj-y += bus.o reset.o
-common-obj-y += fw-path-provider.o
+common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
+common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
 # irq.o needed for qdev GPIO handling:
 common-obj-y += irq.o
 common-obj-y += hotplug.o
-common-obj-y += nmi.o
+common-obj-$(CONFIG_SOFTMMU) += nmi.o
 
 common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
 common-obj-$(CONFIG_XILINX_AXI) += stream.o
diff --git a/hw/core/qdev-fw.c b/hw/core/qdev-fw.c
new file mode 100644
index 0000000000..aa35e9d0ac
--- /dev/null
+++ b/hw/core/qdev-fw.c
@@ -0,0 +1,96 @@
+/*
+ *  qdev fw helpers
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License,
+ *  or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev.h"
+#include "hw/fw-path-provider.h"
+
+const char *qdev_fw_name(DeviceState *dev)
+{
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+    if (dc->fw_name) {
+        return dc->fw_name;
+    }
+
+    return object_get_typename(OBJECT(dev));
+}
+
+static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+
+    if (bc->get_fw_dev_path) {
+        return bc->get_fw_dev_path(dev);
+    }
+
+    return NULL;
+}
+
+static char *qdev_get_fw_dev_path_from_handler(BusState *bus, DeviceState *dev)
+{
+    Object *obj = OBJECT(dev);
+    char *d = NULL;
+
+    while (!d && obj->parent) {
+        obj = obj->parent;
+        d = fw_path_provider_try_get_dev_path(obj, bus, dev);
+    }
+    return d;
+}
+
+char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev)
+{
+    Object *obj = OBJECT(dev);
+
+    return fw_path_provider_try_get_dev_path(obj, bus, dev);
+}
+
+static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
+{
+    int l = 0;
+
+    if (dev && dev->parent_bus) {
+        char *d;
+        l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
+        d = qdev_get_fw_dev_path_from_handler(dev->parent_bus, dev);
+        if (!d) {
+            d = bus_get_fw_dev_path(dev->parent_bus, dev);
+        }
+        if (d) {
+            l += snprintf(p + l, size - l, "%s", d);
+            g_free(d);
+        } else {
+            return l;
+        }
+    }
+    l += snprintf(p + l , size - l, "/");
+
+    return l;
+}
+
+char *qdev_get_fw_dev_path(DeviceState *dev)
+{
+    char path[128];
+    int l;
+
+    l = qdev_get_fw_dev_path_helper(dev, path, 128);
+
+    path[l - 1] = '\0';
+
+    return g_strdup(path);
+}
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index f739753e3a..2456035d1a 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -27,7 +27,6 @@
 
 #include "qemu/osdep.h"
 #include "hw/qdev.h"
-#include "hw/fw-path-provider.h"
 #include "sysemu/sysemu.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
@@ -48,17 +47,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
     return dc->vmsd;
 }
 
-const char *qdev_fw_name(DeviceState *dev)
-{
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-
-    if (dc->fw_name) {
-        return dc->fw_name;
-    }
-
-    return object_get_typename(OBJECT(dev));
-}
-
 static void bus_remove_child(BusState *bus, DeviceState *child)
 {
     BusChild *kid;
@@ -631,71 +619,6 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id)
     return NULL;
 }
 
-static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
-{
-    BusClass *bc = BUS_GET_CLASS(bus);
-
-    if (bc->get_fw_dev_path) {
-        return bc->get_fw_dev_path(dev);
-    }
-
-    return NULL;
-}
-
-static char *qdev_get_fw_dev_path_from_handler(BusState *bus, DeviceState *dev)
-{
-    Object *obj = OBJECT(dev);
-    char *d = NULL;
-
-    while (!d && obj->parent) {
-        obj = obj->parent;
-        d = fw_path_provider_try_get_dev_path(obj, bus, dev);
-    }
-    return d;
-}
-
-char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev)
-{
-    Object *obj = OBJECT(dev);
-
-    return fw_path_provider_try_get_dev_path(obj, bus, dev);
-}
-
-static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
-{
-    int l = 0;
-
-    if (dev && dev->parent_bus) {
-        char *d;
-        l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
-        d = qdev_get_fw_dev_path_from_handler(dev->parent_bus, dev);
-        if (!d) {
-            d = bus_get_fw_dev_path(dev->parent_bus, dev);
-        }
-        if (d) {
-            l += snprintf(p + l, size - l, "%s", d);
-            g_free(d);
-        } else {
-            return l;
-        }
-    }
-    l += snprintf(p + l , size - l, "/");
-
-    return l;
-}
-
-char* qdev_get_fw_dev_path(DeviceState *dev)
-{
-    char path[128];
-    int l;
-
-    l = qdev_get_fw_dev_path_helper(dev, path, 128);
-
-    path[l-1] = '\0';
-
-    return g_strdup(path);
-}
-
 char *qdev_get_dev_path(DeviceState *dev)
 {
     BusClass *bc;
diff --git a/hw/display/vga.c b/hw/display/vga.c
index a0412000a5..6e78a4e156 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1279,6 +1279,9 @@ static void vga_draw_text(VGACommonState *s, int full_update)
         cx_min = width;
         cx_max = -1;
         for(cx = 0; cx < width; cx++) {
+            if (src + sizeof(uint16_t) > s->vram_ptr + s->vram_size) {
+                break;
+            }
             ch_attr = *(uint16_t *)src;
             if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
                 if (cx < cx_min)
diff --git a/hw/s390x/s390-stattrib-kvm.c b/hw/s390x/s390-stattrib-kvm.c
index 41770a7dec..480551c3db 100644
--- a/hw/s390x/s390-stattrib-kvm.c
+++ b/hw/s390x/s390-stattrib-kvm.c
@@ -116,7 +116,7 @@ static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
         for (cx = 0; cx + len <= max; cx += len) {
             clog.start_gfn = cx;
             clog.count = len;
-            clog.values = (uint64_t)(sas->incoming_buffer + cx * len);
+            clog.values = (uint64_t)(sas->incoming_buffer + cx);
             r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
             if (r) {
                 error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
@@ -126,7 +126,7 @@ static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
         if (cx < max) {
             clog.start_gfn = cx;
             clog.count = max - cx;
-            clog.values = (uint64_t)(sas->incoming_buffer + cx * len);
+            clog.values = (uint64_t)(sas->incoming_buffer + cx);
             r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
             if (r) {
                 error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 9be0cb80ad..276972b59f 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -67,7 +67,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
     prepare_cpu_entries(sclp, read_info->entries, &cpu_count);
     read_info->entries_cpu = cpu_to_be16(cpu_count);
     read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
-    read_info->highest_cpu = cpu_to_be16(max_cpus);
+    read_info->highest_cpu = cpu_to_be16(max_cpus - 1);
 
     read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
 
@@ -233,7 +233,7 @@ static void assign_storage(SCLPDevice *sclp, SCCB *sccb)
         sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
         return;
     }
-    assign_addr = (assign_info->rn - 1) * mhd->rzm;
+    assign_addr = (be16_to_cpu(assign_info->rn) - 1) * mhd->rzm;
 
     if ((assign_addr % MEM_SECTION_SIZE == 0) &&
         (assign_addr >= mhd->padded_ram_size)) {
@@ -292,7 +292,7 @@ static void unassign_storage(SCLPDevice *sclp, SCCB *sccb)
         sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
         return;
     }
-    unassign_addr = (assign_info->rn - 1) * mhd->rzm;
+    unassign_addr = (be16_to_cpu(assign_info->rn) - 1) * mhd->rzm;
 
     /* if the addr is a multiple of 256 MB */
     if ((unassign_addr % MEM_SECTION_SIZE == 0) &&
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 38f6a8afc9..3d8f26949b 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -426,8 +426,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                  * passes us zeroes for those we don't support.
                  */
                 if (features.features) {
-                    fprintf(stderr, "Guest bug: features[%i]=%x (expected 0)\n",
-                            features.index, features.features);
+                    qemu_log_mask(LOG_GUEST_ERROR,
+                                  "Guest bug: features[%i]=%x (expected 0)",
+                                  features.index, features.features);
                     /* XXX: do a unit check here? */
                 }
             }
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 8106346927..3042232daf 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -256,15 +256,6 @@ bool virtio_bus_ioeventfd_enabled(VirtioBusState *bus)
     return k->ioeventfd_assign && k->ioeventfd_enabled(proxy);
 }
 
-static void virtio_bus_cleanup_event_notifier(EventNotifier *notifier)
-{
-    /* Test and clear notifier after disabling event,
-     * in case poll callback didn't have time to run.
-     */
-    virtio_queue_host_notifier_read(notifier);
-    event_notifier_cleanup(notifier);
-}
-
 /*
  * This function switches ioeventfd on/off in the device.
  * The caller must set or clear the handlers for the EventNotifier.
@@ -292,13 +283,19 @@ int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign)
         r = k->ioeventfd_assign(proxy, notifier, n, true);
         if (r < 0) {
             error_report("%s: unable to assign ioeventfd: %d", __func__, r);
-            virtio_bus_cleanup_event_notifier(notifier);
+            goto cleanup_event_notifier;
         }
+        return 0;
     } else {
-        notifier->cleanup = virtio_bus_cleanup_event_notifier;
         k->ioeventfd_assign(proxy, notifier, n, false);
     }
 
+cleanup_event_notifier:
+    /* Test and clear notifier after disabling event,
+     * in case poll callback didn't have time to run.
+     */
+    virtio_queue_host_notifier_read(notifier);
+    event_notifier_cleanup(notifier);
     return r;
 }
 
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 3ac3491bee..d6002ee550 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2574,7 +2574,6 @@ static int virtio_device_start_ioeventfd_impl(VirtIODevice *vdev)
     VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
     int n, r, err;
 
-    memory_region_transaction_begin();
     for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
         VirtQueue *vq = &vdev->vq[n];
         if (!virtio_queue_get_num(vdev, n)) {
@@ -2597,7 +2596,6 @@ static int virtio_device_start_ioeventfd_impl(VirtIODevice *vdev)
         }
         event_notifier_set(&vq->host_notifier);
     }
-    memory_region_transaction_commit();
     return 0;
 
 assign_error:
@@ -2611,7 +2609,6 @@ assign_error:
         r = virtio_bus_set_host_notifier(qbus, n, false);
         assert(r >= 0);
     }
-    memory_region_transaction_commit();
     return err;
 }
 
@@ -2628,7 +2625,6 @@ static void virtio_device_stop_ioeventfd_impl(VirtIODevice *vdev)
     VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
     int n, r;
 
-    memory_region_transaction_begin();
     for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
         VirtQueue *vq = &vdev->vq[n];
 
@@ -2639,7 +2635,6 @@ static void virtio_device_stop_ioeventfd_impl(VirtIODevice *vdev)
         r = virtio_bus_set_host_notifier(qbus, n, false);
         assert(r >= 0);
     }
-    memory_region_transaction_commit();
 }
 
 void virtio_device_stop_ioeventfd(VirtIODevice *vdev)
diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs
index cb77dc3793..cb4998d2bf 100644
--- a/hw/xtensa/Makefile.objs
+++ b/hw/xtensa/Makefile.objs
@@ -1,3 +1,4 @@
 obj-y += pic_cpu.o
 obj-y += sim.o
+obj-y += xtensa_memory.o
 obj-y += xtfpga.o
diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c
index 2bb883b664..5c0ba231d1 100644
--- a/hw/xtensa/sim.c
+++ b/hw/xtensa/sim.c
@@ -36,25 +36,7 @@
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 #include "qemu/error-report.h"
-
-static void xtensa_create_memory_regions(const XtensaMemory *memory,
-                                         const char *name)
-{
-    unsigned i;
-    GString *num_name = g_string_new(NULL);
-
-    for (i = 0; i < memory->num; ++i) {
-        MemoryRegion *m;
-
-        g_string_printf(num_name, "%s%u", name, i);
-        m = g_new(MemoryRegion, 1);
-        memory_region_init_ram(m, NULL, num_name->str,
-                               memory->location[i].size, &error_fatal);
-        memory_region_add_subregion(get_system_memory(),
-                                    memory->location[i].addr, m);
-    }
-    g_string_free(num_name, true);
-}
+#include "xtensa_memory.h"
 
 static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
 {
@@ -94,12 +76,18 @@ static void xtensa_sim_init(MachineState *machine)
         XtensaMemory sysram = env->config->sysram;
 
         sysram.location[0].size = ram_size;
-        xtensa_create_memory_regions(&env->config->instrom, "xtensa.instrom");
-        xtensa_create_memory_regions(&env->config->instram, "xtensa.instram");
-        xtensa_create_memory_regions(&env->config->datarom, "xtensa.datarom");
-        xtensa_create_memory_regions(&env->config->dataram, "xtensa.dataram");
-        xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom");
-        xtensa_create_memory_regions(&sysram, "xtensa.sysram");
+        xtensa_create_memory_regions(&env->config->instrom, "xtensa.instrom",
+                                     get_system_memory());
+        xtensa_create_memory_regions(&env->config->instram, "xtensa.instram",
+                                     get_system_memory());
+        xtensa_create_memory_regions(&env->config->datarom, "xtensa.datarom",
+                                     get_system_memory());
+        xtensa_create_memory_regions(&env->config->dataram, "xtensa.dataram",
+                                     get_system_memory());
+        xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom",
+                                     get_system_memory());
+        xtensa_create_memory_regions(&sysram, "xtensa.sysram",
+                                     get_system_memory());
     }
 
     if (serial_hds[0]) {
diff --git a/hw/xtensa/xtensa_memory.c b/hw/xtensa/xtensa_memory.c
new file mode 100644
index 0000000000..394967f842
--- /dev/null
+++ b/hw/xtensa/xtensa_memory.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "exec/memory.h"
+#include "qemu/error-report.h"
+#include "xtensa_memory.h"
+
+void xtensa_create_memory_regions(const XtensaMemory *memory,
+                                  const char *name,
+                                  MemoryRegion *super)
+{
+    unsigned i;
+    GString *num_name = g_string_new(NULL);
+
+    for (i = 0; i < memory->num; ++i) {
+        MemoryRegion *m;
+
+        g_string_printf(num_name, "%s%u", name, i);
+        m = g_new(MemoryRegion, 1);
+        memory_region_init_ram(m, NULL, num_name->str,
+                               memory->location[i].size, &error_fatal);
+        memory_region_add_subregion(super, memory->location[i].addr, m);
+    }
+    g_string_free(num_name, true);
+}
diff --git a/hw/xtensa/xtensa_memory.h b/hw/xtensa/xtensa_memory.h
new file mode 100644
index 0000000000..cab4d172d4
--- /dev/null
+++ b/hw/xtensa/xtensa_memory.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _XTENSA_MEMORY_H
+#define _XTENSA_MEMORY_H
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "exec/memory.h"
+
+void xtensa_create_memory_regions(const XtensaMemory *memory,
+                                  const char *name,
+                                  MemoryRegion *super);
+
+#endif
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 1971ecfdc5..76ea970215 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -44,33 +44,39 @@
 #include "sysemu/device_tree.h"
 #include "qemu/error-report.h"
 #include "bootparam.h"
+#include "xtensa_memory.h"
 
-typedef struct LxBoardDesc {
-    hwaddr flash_base;
-    size_t flash_size;
-    size_t flash_boot_base;
-    size_t flash_sector_size;
+typedef struct XtfpgaFlashDesc {
+    hwaddr base;
+    size_t size;
+    size_t boot_base;
+    size_t sector_size;
+} XtfpgaFlashDesc;
+
+typedef struct XtfpgaBoardDesc {
+    const XtfpgaFlashDesc *flash;
     size_t sram_size;
-} LxBoardDesc;
+    const hwaddr *io;
+} XtfpgaBoardDesc;
 
-typedef struct Lx60FpgaState {
+typedef struct XtfpgaFpgaState {
     MemoryRegion iomem;
     uint32_t leds;
     uint32_t switches;
-} Lx60FpgaState;
+} XtfpgaFpgaState;
 
-static void lx60_fpga_reset(void *opaque)
+static void xtfpga_fpga_reset(void *opaque)
 {
-    Lx60FpgaState *s = opaque;
+    XtfpgaFpgaState *s = opaque;
 
     s->leds = 0;
     s->switches = 0;
 }
 
-static uint64_t lx60_fpga_read(void *opaque, hwaddr addr,
+static uint64_t xtfpga_fpga_read(void *opaque, hwaddr addr,
         unsigned size)
 {
-    Lx60FpgaState *s = opaque;
+    XtfpgaFpgaState *s = opaque;
 
     switch (addr) {
     case 0x0: /*build date code*/
@@ -88,10 +94,10 @@ static uint64_t lx60_fpga_read(void *opaque, hwaddr addr,
     return 0;
 }
 
-static void lx60_fpga_write(void *opaque, hwaddr addr,
+static void xtfpga_fpga_write(void *opaque, hwaddr addr,
         uint64_t val, unsigned size)
 {
-    Lx60FpgaState *s = opaque;
+    XtfpgaFpgaState *s = opaque;
 
     switch (addr) {
     case 0x8: /*LEDs (off = 0, on = 1)*/
@@ -106,26 +112,26 @@ static void lx60_fpga_write(void *opaque, hwaddr addr,
     }
 }
 
-static const MemoryRegionOps lx60_fpga_ops = {
-    .read = lx60_fpga_read,
-    .write = lx60_fpga_write,
+static const MemoryRegionOps xtfpga_fpga_ops = {
+    .read = xtfpga_fpga_read,
+    .write = xtfpga_fpga_write,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space,
+static XtfpgaFpgaState *xtfpga_fpga_init(MemoryRegion *address_space,
         hwaddr base)
 {
-    Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
+    XtfpgaFpgaState *s = g_malloc(sizeof(XtfpgaFpgaState));
 
-    memory_region_init_io(&s->iomem, NULL, &lx60_fpga_ops, s,
-            "lx60.fpga", 0x10000);
+    memory_region_init_io(&s->iomem, NULL, &xtfpga_fpga_ops, s,
+            "xtfpga.fpga", 0x10000);
     memory_region_add_subregion(address_space, base, &s->iomem);
-    lx60_fpga_reset(s);
-    qemu_register_reset(lx60_fpga_reset, s);
+    xtfpga_fpga_reset(s);
+    qemu_register_reset(xtfpga_fpga_reset, s);
     return s;
 }
 
-static void lx60_net_init(MemoryRegion *address_space,
+static void xtfpga_net_init(MemoryRegion *address_space,
         hwaddr base,
         hwaddr descriptors,
         hwaddr buffers,
@@ -154,7 +160,7 @@ static void lx60_net_init(MemoryRegion *address_space,
 }
 
 static pflash_t *xtfpga_flash_init(MemoryRegion *address_space,
-                                   const LxBoardDesc *board,
+                                   const XtfpgaBoardDesc *board,
                                    DriveInfo *dinfo, int be)
 {
     SysBusDevice *s;
@@ -163,14 +169,14 @@ static pflash_t *xtfpga_flash_init(MemoryRegion *address_space,
     qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
                         &error_abort);
     qdev_prop_set_uint32(dev, "num-blocks",
-                         board->flash_size / board->flash_sector_size);
-    qdev_prop_set_uint64(dev, "sector-length", board->flash_sector_size);
+                         board->flash->size / board->flash->sector_size);
+    qdev_prop_set_uint64(dev, "sector-length", board->flash->sector_size);
     qdev_prop_set_uint8(dev, "width", 2);
     qdev_prop_set_bit(dev, "big-endian", be);
-    qdev_prop_set_string(dev, "name", "lx60.io.flash");
+    qdev_prop_set_string(dev, "name", "xtfpga.io.flash");
     qdev_init_nofail(dev);
     s = SYS_BUS_DEVICE(dev);
-    memory_region_add_subregion(address_space, board->flash_base,
+    memory_region_add_subregion(address_space, board->flash->base,
                                 sysbus_mmio_get_region(s, 0));
     return OBJECT_CHECK(pflash_t, (dev), "cfi.pflash01");
 }
@@ -182,31 +188,31 @@ static uint64_t translate_phys_addr(void *opaque, uint64_t addr)
     return cpu_get_phys_page_debug(CPU(cpu), addr);
 }
 
-static void lx60_reset(void *opaque)
+static void xtfpga_reset(void *opaque)
 {
     XtensaCPU *cpu = opaque;
 
     cpu_reset(CPU(cpu));
 }
 
-static uint64_t lx60_io_read(void *opaque, hwaddr addr,
+static uint64_t xtfpga_io_read(void *opaque, hwaddr addr,
         unsigned size)
 {
     return 0;
 }
 
-static void lx60_io_write(void *opaque, hwaddr addr,
+static void xtfpga_io_write(void *opaque, hwaddr addr,
         uint64_t val, unsigned size)
 {
 }
 
-static const MemoryRegionOps lx60_io_ops = {
-    .read = lx60_io_read,
-    .write = lx60_io_write,
+static const MemoryRegionOps xtfpga_io_ops = {
+    .read = xtfpga_io_read,
+    .write = xtfpga_io_write,
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void lx_init(const LxBoardDesc *board, MachineState *machine)
+static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
 {
 #ifdef TARGET_WORDS_BIGENDIAN
     int be = 1;
@@ -216,7 +222,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
     MemoryRegion *system_memory = get_system_memory();
     XtensaCPU *cpu = NULL;
     CPUXtensaState *env = NULL;
-    MemoryRegion *ram, *rom, *system_io;
+    MemoryRegion *system_io;
     DriveInfo *dinfo;
     pflash_t *flash = NULL;
     QemuOpts *machine_opts = qemu_get_machine_opts();
@@ -224,6 +230,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
     const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
     const char *dtb_filename = qemu_opt_get(machine_opts, "dtb");
     const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
+    const unsigned system_io_size = 224 * 1024 * 1024;
     int n;
 
     for (n = 0; n < smp_cpus; n++) {
@@ -231,25 +238,43 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
         env = &cpu->env;
 
         env->sregs[PRID] = n;
-        qemu_register_reset(lx60_reset, cpu);
+        qemu_register_reset(xtfpga_reset, cpu);
         /* Need MMU initialized prior to ELF loading,
          * so that ELF gets loaded into virtual addresses
          */
         cpu_reset(CPU(cpu));
     }
 
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "lx60.dram", machine->ram_size,
-                           &error_fatal);
-    memory_region_add_subregion(system_memory, 0, ram);
+    if (env) {
+        XtensaMemory sysram = env->config->sysram;
+
+        sysram.location[0].size = machine->ram_size;
+        xtensa_create_memory_regions(&env->config->instrom, "xtensa.instrom",
+                                     system_memory);
+        xtensa_create_memory_regions(&env->config->instram, "xtensa.instram",
+                                     system_memory);
+        xtensa_create_memory_regions(&env->config->datarom, "xtensa.datarom",
+                                     system_memory);
+        xtensa_create_memory_regions(&env->config->dataram, "xtensa.dataram",
+                                     system_memory);
+        xtensa_create_memory_regions(&sysram, "xtensa.sysram",
+                                     system_memory);
+    }
 
     system_io = g_malloc(sizeof(*system_io));
-    memory_region_init_io(system_io, NULL, &lx60_io_ops, NULL, "lx60.io",
-                          224 * 1024 * 1024);
-    memory_region_add_subregion(system_memory, 0xf0000000, system_io);
-    lx60_fpga_init(system_io, 0x0d020000);
+    memory_region_init_io(system_io, NULL, &xtfpga_io_ops, NULL, "xtfpga.io",
+                          system_io_size);
+    memory_region_add_subregion(system_memory, board->io[0], system_io);
+    if (board->io[1]) {
+        MemoryRegion *io = g_malloc(sizeof(*io));
+
+        memory_region_init_alias(io, NULL, "xtfpga.io.cached",
+                                 system_io, 0, system_io_size);
+        memory_region_add_subregion(system_memory, board->io[1], io);
+    }
+    xtfpga_fpga_init(system_io, 0x0d020000);
     if (nd_table[0].used) {
-        lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
+        xtfpga_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
                 xtensa_get_extint(env, 1), nd_table);
     }
 
@@ -269,21 +294,24 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
     if (kernel_filename) {
         uint32_t entry_point = env->pc;
         size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */
-        uint32_t tagptr = 0xfe000000 + board->sram_size;
+        uint32_t tagptr = env->config->sysrom.location[0].addr +
+            board->sram_size;
         uint32_t cur_tagptr;
         BpMemInfo memory_location = {
             .type = tswap32(MEMORY_TYPE_CONVENTIONAL),
-            .start = tswap32(0),
-            .end = tswap32(machine->ram_size),
+            .start = tswap32(env->config->sysram.location[0].addr),
+            .end = tswap32(env->config->sysram.location[0].addr +
+                           machine->ram_size),
         };
         uint32_t lowmem_end = machine->ram_size < 0x08000000 ?
             machine->ram_size : 0x08000000;
         uint32_t cur_lowmem = QEMU_ALIGN_UP(lowmem_end / 2, 4096);
 
-        rom = g_malloc(sizeof(*rom));
-        memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size,
-                               &error_fatal);
-        memory_region_add_subregion(system_memory, 0xfe000000, rom);
+        lowmem_end += env->config->sysram.location[0].addr;
+        cur_lowmem += env->config->sysram.location[0].addr;
+
+        xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom",
+                                     system_memory);
 
         if (kernel_cmdline) {
             bp_size += get_tag_size(strlen(kernel_cmdline) + 1);
@@ -372,146 +400,308 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
             }
         }
         if (entry_point != env->pc) {
-            static const uint8_t jx_a0[] = {
+            uint8_t boot[] = {
 #ifdef TARGET_WORDS_BIGENDIAN
-                0x0a, 0, 0,
+                0x60, 0x00, 0x08,       /* j    1f */
+                0x00,                   /* .literal_position */
+                0x00, 0x00, 0x00, 0x00, /* .literal entry_pc */
+                0x00, 0x00, 0x00, 0x00, /* .literal entry_a2 */
+                                        /* 1: */
+                0x10, 0xff, 0xfe,       /* l32r a0, entry_pc */
+                0x12, 0xff, 0xfe,       /* l32r a2, entry_a2 */
+                0x0a, 0x00, 0x00,       /* jx   a0 */
 #else
-                0xa0, 0, 0,
+                0x06, 0x02, 0x00,       /* j    1f */
+                0x00,                   /* .literal_position */
+                0x00, 0x00, 0x00, 0x00, /* .literal entry_pc */
+                0x00, 0x00, 0x00, 0x00, /* .literal entry_a2 */
+                                        /* 1: */
+                0x01, 0xfe, 0xff,       /* l32r a0, entry_pc */
+                0x21, 0xfe, 0xff,       /* l32r a2, entry_a2 */
+                0xa0, 0x00, 0x00,       /* jx   a0 */
 #endif
             };
-            env->regs[0] = entry_point;
-            cpu_physical_memory_write(env->pc, jx_a0, sizeof(jx_a0));
+            uint32_t entry_pc = tswap32(entry_point);
+            uint32_t entry_a2 = tswap32(tagptr);
+
+            memcpy(boot + 4, &entry_pc, sizeof(entry_pc));
+            memcpy(boot + 8, &entry_a2, sizeof(entry_a2));
+            cpu_physical_memory_write(env->pc, boot, sizeof(boot));
         }
     } else {
         if (flash) {
             MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
             MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
+            uint32_t size = env->config->sysrom.location[0].size;
 
-            memory_region_init_alias(flash_io, NULL, "lx60.flash",
-                    flash_mr, board->flash_boot_base,
-                    board->flash_size - board->flash_boot_base < 0x02000000 ?
-                    board->flash_size - board->flash_boot_base : 0x02000000);
-            memory_region_add_subregion(system_memory, 0xfe000000,
-                    flash_io);
+            if (board->flash->size - board->flash->boot_base < size) {
+                size = board->flash->size - board->flash->boot_base;
+            }
+
+            memory_region_init_alias(flash_io, NULL, "xtfpga.flash",
+                                     flash_mr, board->flash->boot_base, size);
+            memory_region_add_subregion(system_memory,
+                                        env->config->sysrom.location[0].addr,
+                                        flash_io);
+        } else {
+            xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom",
+                                         system_memory);
         }
     }
 }
 
-static void xtensa_lx60_init(MachineState *machine)
+static const hwaddr xtfpga_mmu_io[2] = {
+    0xf0000000,
+};
+
+static const hwaddr xtfpga_nommu_io[2] = {
+    0x90000000,
+    0x70000000,
+};
+
+static const XtfpgaFlashDesc lx60_flash = {
+    .base = 0x08000000,
+    .size = 0x00400000,
+    .sector_size = 0x10000,
+};
+
+static void xtfpga_lx60_init(MachineState *machine)
 {
-    static const LxBoardDesc lx60_board = {
-        .flash_base = 0x08000000,
-        .flash_size = 0x00400000,
-        .flash_sector_size = 0x10000,
+    static const XtfpgaBoardDesc lx60_board = {
+        .flash = &lx60_flash,
         .sram_size = 0x20000,
+        .io = xtfpga_mmu_io,
+    };
+    xtfpga_init(&lx60_board, machine);
+}
+
+static void xtfpga_lx60_nommu_init(MachineState *machine)
+{
+    static const XtfpgaBoardDesc lx60_board = {
+        .flash = &lx60_flash,
+        .sram_size = 0x20000,
+        .io = xtfpga_nommu_io,
+    };
+    xtfpga_init(&lx60_board, machine);
+}
+
+static const XtfpgaFlashDesc lx200_flash = {
+    .base = 0x08000000,
+    .size = 0x01000000,
+    .sector_size = 0x20000,
+};
+
+static void xtfpga_lx200_init(MachineState *machine)
+{
+    static const XtfpgaBoardDesc lx200_board = {
+        .flash = &lx200_flash,
+        .sram_size = 0x2000000,
+        .io = xtfpga_mmu_io,
+    };
+    xtfpga_init(&lx200_board, machine);
+}
+
+static void xtfpga_lx200_nommu_init(MachineState *machine)
+{
+    static const XtfpgaBoardDesc lx200_board = {
+        .flash = &lx200_flash,
+        .sram_size = 0x2000000,
+        .io = xtfpga_nommu_io,
+    };
+    xtfpga_init(&lx200_board, machine);
+}
+
+static const XtfpgaFlashDesc ml605_flash = {
+    .base = 0x08000000,
+    .size = 0x01000000,
+    .sector_size = 0x20000,
+};
+
+static void xtfpga_ml605_init(MachineState *machine)
+{
+    static const XtfpgaBoardDesc ml605_board = {
+        .flash = &ml605_flash,
+        .sram_size = 0x2000000,
+        .io = xtfpga_mmu_io,
     };
-    lx_init(&lx60_board, machine);
+    xtfpga_init(&ml605_board, machine);
 }
 
-static void xtensa_lx200_init(MachineState *machine)
+static void xtfpga_ml605_nommu_init(MachineState *machine)
 {
-    static const LxBoardDesc lx200_board = {
-        .flash_base = 0x08000000,
-        .flash_size = 0x01000000,
-        .flash_sector_size = 0x20000,
+    static const XtfpgaBoardDesc ml605_board = {
+        .flash = &ml605_flash,
         .sram_size = 0x2000000,
+        .io = xtfpga_nommu_io,
     };
-    lx_init(&lx200_board, machine);
+    xtfpga_init(&ml605_board, machine);
 }
 
-static void xtensa_ml605_init(MachineState *machine)
+static const XtfpgaFlashDesc kc705_flash = {
+    .base = 0x00000000,
+    .size = 0x08000000,
+    .boot_base = 0x06000000,
+    .sector_size = 0x20000,
+};
+
+static void xtfpga_kc705_init(MachineState *machine)
 {
-    static const LxBoardDesc ml605_board = {
-        .flash_base = 0x08000000,
-        .flash_size = 0x01000000,
-        .flash_sector_size = 0x20000,
+    static const XtfpgaBoardDesc kc705_board = {
+        .flash = &kc705_flash,
         .sram_size = 0x2000000,
+        .io = xtfpga_mmu_io,
     };
-    lx_init(&ml605_board, machine);
+    xtfpga_init(&kc705_board, machine);
 }
 
-static void xtensa_kc705_init(MachineState *machine)
+static void xtfpga_kc705_nommu_init(MachineState *machine)
 {
-    static const LxBoardDesc kc705_board = {
-        .flash_base = 0x00000000,
-        .flash_size = 0x08000000,
-        .flash_boot_base = 0x06000000,
-        .flash_sector_size = 0x20000,
+    static const XtfpgaBoardDesc kc705_board = {
+        .flash = &kc705_flash,
         .sram_size = 0x2000000,
+        .io = xtfpga_nommu_io,
     };
-    lx_init(&kc705_board, machine);
+    xtfpga_init(&kc705_board, machine);
 }
 
-static void xtensa_lx60_class_init(ObjectClass *oc, void *data)
+static void xtfpga_lx60_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
 
     mc->desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
-    mc->init = xtensa_lx60_init;
+    mc->init = xtfpga_lx60_init;
     mc->max_cpus = 4;
     mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
 }
 
-static const TypeInfo xtensa_lx60_type = {
+static const TypeInfo xtfpga_lx60_type = {
     .name = MACHINE_TYPE_NAME("lx60"),
     .parent = TYPE_MACHINE,
-    .class_init = xtensa_lx60_class_init,
+    .class_init = xtfpga_lx60_class_init,
+};
+
+static void xtfpga_lx60_nommu_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "lx60 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
+    mc->init = xtfpga_lx60_nommu_init;
+    mc->max_cpus = 4;
+    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
+}
+
+static const TypeInfo xtfpga_lx60_nommu_type = {
+    .name = MACHINE_TYPE_NAME("lx60-nommu"),
+    .parent = TYPE_MACHINE,
+    .class_init = xtfpga_lx60_nommu_class_init,
 };
 
-static void xtensa_lx200_class_init(ObjectClass *oc, void *data)
+static void xtfpga_lx200_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
 
     mc->desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
-    mc->init = xtensa_lx200_init;
+    mc->init = xtfpga_lx200_init;
     mc->max_cpus = 4;
     mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
 }
 
-static const TypeInfo xtensa_lx200_type = {
+static const TypeInfo xtfpga_lx200_type = {
     .name = MACHINE_TYPE_NAME("lx200"),
     .parent = TYPE_MACHINE,
-    .class_init = xtensa_lx200_class_init,
+    .class_init = xtfpga_lx200_class_init,
 };
 
-static void xtensa_ml605_class_init(ObjectClass *oc, void *data)
+static void xtfpga_lx200_nommu_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "lx200 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
+    mc->init = xtfpga_lx200_nommu_init;
+    mc->max_cpus = 4;
+    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
+}
+
+static const TypeInfo xtfpga_lx200_nommu_type = {
+    .name = MACHINE_TYPE_NAME("lx200-nommu"),
+    .parent = TYPE_MACHINE,
+    .class_init = xtfpga_lx200_nommu_class_init,
+};
+
+static void xtfpga_ml605_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
 
     mc->desc = "ml605 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
-    mc->init = xtensa_ml605_init;
+    mc->init = xtfpga_ml605_init;
     mc->max_cpus = 4;
     mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
 }
 
-static const TypeInfo xtensa_ml605_type = {
+static const TypeInfo xtfpga_ml605_type = {
     .name = MACHINE_TYPE_NAME("ml605"),
     .parent = TYPE_MACHINE,
-    .class_init = xtensa_ml605_class_init,
+    .class_init = xtfpga_ml605_class_init,
+};
+
+static void xtfpga_ml605_nommu_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "ml605 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
+    mc->init = xtfpga_ml605_nommu_init;
+    mc->max_cpus = 4;
+    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
+}
+
+static const TypeInfo xtfpga_ml605_nommu_type = {
+    .name = MACHINE_TYPE_NAME("ml605-nommu"),
+    .parent = TYPE_MACHINE,
+    .class_init = xtfpga_ml605_nommu_class_init,
 };
 
-static void xtensa_kc705_class_init(ObjectClass *oc, void *data)
+static void xtfpga_kc705_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
 
     mc->desc = "kc705 EVB (" XTENSA_DEFAULT_CPU_MODEL ")";
-    mc->init = xtensa_kc705_init;
+    mc->init = xtfpga_kc705_init;
     mc->max_cpus = 4;
     mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE;
 }
 
-static const TypeInfo xtensa_kc705_type = {
+static const TypeInfo xtfpga_kc705_type = {
     .name = MACHINE_TYPE_NAME("kc705"),
     .parent = TYPE_MACHINE,
-    .class_init = xtensa_kc705_class_init,
+    .class_init = xtfpga_kc705_class_init,
+};
+
+static void xtfpga_kc705_nommu_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "kc705 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")";
+    mc->init = xtfpga_kc705_nommu_init;
+    mc->max_cpus = 4;
+    mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE;
+}
+
+static const TypeInfo xtfpga_kc705_nommu_type = {
+    .name = MACHINE_TYPE_NAME("kc705-nommu"),
+    .parent = TYPE_MACHINE,
+    .class_init = xtfpga_kc705_nommu_class_init,
 };
 
-static void xtensa_lx_machines_init(void)
+static void xtfpga_machines_init(void)
 {
-    type_register_static(&xtensa_lx60_type);
-    type_register_static(&xtensa_lx200_type);
-    type_register_static(&xtensa_ml605_type);
-    type_register_static(&xtensa_kc705_type);
+    type_register_static(&xtfpga_lx60_type);
+    type_register_static(&xtfpga_lx200_type);
+    type_register_static(&xtfpga_ml605_type);
+    type_register_static(&xtfpga_kc705_type);
+    type_register_static(&xtfpga_lx60_nommu_type);
+    type_register_static(&xtfpga_lx200_nommu_type);
+    type_register_static(&xtfpga_ml605_nommu_type);
+    type_register_static(&xtfpga_kc705_nommu_type);
 }
 
-type_init(xtensa_lx_machines_init)
+type_init(xtfpga_machines_init)