]> Git Repo - qemu.git/commitdiff
Merge remote-tracking branch 'qmp/queue/qmp' into staging
authorAnthony Liguori <[email protected]>
Mon, 10 Oct 2011 13:21:46 +0000 (08:21 -0500)
committerAnthony Liguori <[email protected]>
Mon, 10 Oct 2011 13:21:46 +0000 (08:21 -0500)
124 files changed:
.gitmodules
Makefile
Makefile.objs
Makefile.target
block.c
block/qed-table.c
block/qed.c
configure
console.c
cpu-exec.c
default-configs/alpha-softmmu.mak
device_tree.c
device_tree.h
gdbstub.c
hmp-commands.hx
hw/adb.c
hw/adb.h [new file with mode: 0644]
hw/alpha_dp264.c [new file with mode: 0644]
hw/alpha_pci.c [new file with mode: 0644]
hw/alpha_sys.h [new file with mode: 0644]
hw/alpha_typhoon.c [new file with mode: 0644]
hw/cs4231a.c
hw/cuda.c
hw/devices.h
hw/etraxfs_dma.c
hw/etraxfs_eth.c
hw/etraxfs_pic.c
hw/etraxfs_ser.c
hw/etraxfs_timer.c
hw/gt64xxx.c
hw/gumstix.c
hw/gus.c
hw/heathrow_pic.c
hw/lsi53c895a.c
hw/mainstone.c
hw/milkymist-ac97.c
hw/milkymist-hpdmc.c
hw/milkymist-hw.h
hw/milkymist-memcard.c
hw/milkymist-minimac2.c
hw/milkymist-pfpu.c
hw/milkymist-softusb.c
hw/milkymist-sysctl.c
hw/milkymist-tmu2.c
hw/milkymist-uart.c
hw/milkymist-vgafb.c
hw/milkymist.c
hw/mips_jazz.c
hw/mips_malta.c
hw/musicpal.c
hw/omap_uart.c
hw/openpic.c
hw/openpic.h
hw/pc.h
hw/petalogix_ml605_mmu.c
hw/ppc.c
hw/ppc.h
hw/ppc405.h
hw/ppc405_boards.c
hw/ppc405_uc.c
hw/ppc440.c
hw/ppc440.h
hw/ppc440_bamboo.c
hw/ppc4xx_devs.c
hw/ppc_booke.c [new file with mode: 0644]
hw/ppc_mac.h
hw/ppc_newworld.c
hw/ppc_oldworld.c
hw/ppce500_mpc8544ds.c
hw/ppce500_spin.c [new file with mode: 0644]
hw/pxa.h
hw/pxa2xx.c
hw/r2d.c
hw/sb16.c
hw/serial.c
hw/sm501.c
hw/smc91c111.c
hw/spapr.c
hw/spapr.h
hw/spapr_hcall.c
hw/spapr_llan.c
hw/spapr_rtas.c
hw/spapr_vio.c
hw/spapr_vio.h
hw/spapr_vscsi.c
hw/spapr_vty.c
hw/spitz.c
hw/sun4u.c
hw/tosa.c
hw/virtex_ml507.c
hw/xics.c
hw/z2.c
linux-headers/asm-powerpc/kvm.h
linux-headers/asm-x86/kvm_para.h
linux-headers/linux/kvm.h
linux-headers/linux/kvm_para.h
linux-user/signal.c
monitor.c
pc-bios/README
pc-bios/mpc8544ds.dtb
pc-bios/mpc8544ds.dts
pc-bios/palcode-clipper [new file with mode: 0755]
ppc64.ld
roms/qemu-palcode [new submodule]
target-alpha/cpu.h
target-alpha/helper.h
target-alpha/op_helper.c
target-alpha/translate.c
target-arm/helper.c
target-arm/op_helper.c
target-i386/cpu.h
target-i386/kvm.c
target-i386/machine.c
target-lm32/helper.c
target-ppc/cpu.h
target-ppc/helper.c
target-ppc/kvm.c
target-ppc/kvm_ppc.c
target-ppc/kvm_ppc.h
target-ppc/translate.c
target-ppc/translate_init.c
tcg/ia64/tcg-target.c
tcg/s390/tcg-target.c
trace-events

index c3faa3879038ee81b918484f69dc070ddfad3e06..2a43dbcd7cc8944cf8d7ec952528bc8e40c107a4 100644 (file)
@@ -13,3 +13,6 @@
 [submodule "roms/openbios"]
        path = roms/openbios
        url = git://git.qemu.org/openbios.git
+[submodule "roms/qemu-palcode"]
+       path = roms/qemu-palcode
+       url = git://repo.or.cz/qemu-palcode.git
index 55ee79c77ae7e6993e6d2a5473d0734911c3426a..f63fc02ca3e3ddd7c447619e5d355936f2c81087 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -146,11 +146,12 @@ endif
 qemu-img.o: qemu-img-cmds.h
 qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
 
-qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
+tools-obj-y = qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) \
+        $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
 
-qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
-
-qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
+qemu-img$(EXESUF): qemu-img.o $(tools-obj-y)
+qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y)
+qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y)
 
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
        $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
@@ -263,7 +264,8 @@ bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
 mpc8544ds.dtb \
 multiboot.bin linuxboot.bin \
 s390-zipl.rom \
-spapr-rtas.bin slof.bin
+spapr-rtas.bin slof.bin \
+palcode-clipper
 else
 BLOBS=
 endif
index a669c62ce5d4d98406c65f14a5e201a4f57d1ce7..7b0739c524e27cdb475b50feb2a7d3e9b24dad43 100644 (file)
@@ -222,7 +222,6 @@ hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
 
 # PPC devices
-hw-obj-$(CONFIG_OPENPIC) += openpic.o
 hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
 # Mac shared devices
 hw-obj-$(CONFIG_MACIO) += macio.o
index b5ed5dffeca8f8572ee1c243b8e4318435ba72fb..42adfecc35452f9c9b61a203becdd07e503809e4 100644 (file)
@@ -229,7 +229,7 @@ obj-i386-$(CONFIG_KVM) += kvmclock.o
 obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 
 # shared objects
-obj-ppc-y = ppc.o
+obj-ppc-y = ppc.o ppc_booke.o
 obj-ppc-y += vga.o
 # PREP target
 obj-ppc-y += i8259.o mc146818rtc.o
@@ -239,19 +239,19 @@ obj-ppc-y += ppc_oldworld.o
 # NewWorld PowerMac
 obj-ppc-y += ppc_newworld.o
 # IBM pSeries (sPAPR)
-ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
-obj-ppc-y += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-ppc-y += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
-endif
+obj-ppc-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
+obj-ppc-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
 # PowerPC 4xx boards
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 obj-ppc-y += ppc440.o ppc440_bamboo.o
 # PowerPC E500 boards
-obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o
+obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-ppc-y += virtex_ml507.o
 obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
 obj-ppc-$(CONFIG_FDT) += device_tree.o
+# PowerPC OpenPIC
+obj-ppc-y += openpic.o
 
 # Xilinx PPC peripherals
 obj-ppc-y += xilinx_intc.o
@@ -367,6 +367,7 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o
 
 obj-alpha-y = i8259.o mc146818rtc.o
 obj-alpha-y += vga.o cirrus_vga.o
+obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
 
 obj-xtensa-y += xtensa_pic.o
 obj-xtensa-y += xtensa_sample.o
diff --git a/block.c b/block.c
index e3fe97f27533ce3f2919a8cff97bba21ce41e362..e865fab27e6d2b57dbf181f23db11fa4a87ed9df 100644 (file)
--- a/block.c
+++ b/block.c
@@ -475,6 +475,8 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
 
     assert(drv != NULL);
 
+    trace_bdrv_open_common(bs, filename, flags, drv->format_name);
+
     bs->file = NULL;
     bs->total_sectors = 0;
     bs->encrypted = 0;
@@ -2997,7 +2999,7 @@ static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num,
                              bdrv_co_io_em_complete, &co);
     }
 
-    trace_bdrv_co_io(is_write, acb);
+    trace_bdrv_co_io_em(bs, sector_num, nb_sectors, is_write, acb);
     if (!acb) {
         return -EIO;
     }
index d96afa81d7cbc9b96d0273a32d5753b4d4cf30c1..f31f9ff069af747658016d6ef2b1c7b613124423 100644 (file)
@@ -222,21 +222,21 @@ static void qed_read_l2_table_cb(void *opaque, int ret)
     QEDRequest *request = read_l2_table_cb->request;
     BDRVQEDState *s = read_l2_table_cb->s;
     CachedL2Table *l2_table = request->l2_table;
+    uint64_t l2_offset = read_l2_table_cb->l2_offset;
 
     if (ret) {
         /* can't trust loaded L2 table anymore */
         qed_unref_l2_cache_entry(l2_table);
         request->l2_table = NULL;
     } else {
-        l2_table->offset = read_l2_table_cb->l2_offset;
+        l2_table->offset = l2_offset;
 
         qed_commit_l2_cache_entry(&s->l2_cache, l2_table);
 
         /* This is guaranteed to succeed because we just committed the entry
          * to the cache.
          */
-        request->l2_table = qed_find_l2_cache_entry(&s->l2_cache,
-                                                    l2_table->offset);
+        request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
         assert(request->l2_table != NULL);
     }
 
index 624e261b359e4dfaf41bfac1db041349c33ceac1..e87dc4decf545f551e311c5c5291fd7637240813 100644 (file)
@@ -911,14 +911,14 @@ static void qed_commit_l2_update(void *opaque, int ret)
     QEDAIOCB *acb = opaque;
     BDRVQEDState *s = acb_to_s(acb);
     CachedL2Table *l2_table = acb->request.l2_table;
+    uint64_t l2_offset = l2_table->offset;
 
     qed_commit_l2_cache_entry(&s->l2_cache, l2_table);
 
     /* This is guaranteed to succeed because we just committed the entry to the
      * cache.
      */
-    acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache,
-                                                    l2_table->offset);
+    acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
     assert(acb->request.l2_table != NULL);
 
     qed_aio_next_io(opaque, ret);
index 59b14947edf8df957b49f8f46a2beec1972160a0..9b4fe34fcef9768bc0d14ac841b65857904b8f71 100755 (executable)
--- a/configure
+++ b/configure
@@ -3389,6 +3389,9 @@ case "$target_arch2" in
       fi
     fi
 esac
+if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
+  echo "CONFIG_PSERIES=y" >> $config_target_mak
+fi
 if test "$target_bigendian" = "yes" ; then
   echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
 fi
@@ -3615,7 +3618,13 @@ FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
 FILES="$FILES pc-bios/spapr-rtas/Makefile"
 FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
-for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+for bios_file in \
+    $source_path/pc-bios/*.bin \
+    $source_path/pc-bios/*.rom \
+    $source_path/pc-bios/*.dtb \
+    $source_path/pc-bios/openbios-* \
+    $source_path/pc-bios/palcode-*
+do
     FILES="$FILES pc-bios/`basename $bios_file`"
 done
 mkdir -p $DIRS
index 6dfcc47940c436fb3d23b6707573b8a9edec79eb..e43de92c00ac02f27c745ea1a1a09c4c2456e79d 100644 (file)
--- a/console.c
+++ b/console.c
@@ -1538,7 +1538,7 @@ int text_console_init(QemuOpts *opts, CharDriverState **_chr)
     }
 
     if (!s) {
-        free(chr);
+        g_free(chr);
         return -EBUSY;
     }
 
index aef66f290ca86b0bd453a4cd99e71a56031dc3b1..a9fa608cff5ad158ad32d0025209a6ea4dc75ac8 100644 (file)
@@ -217,6 +217,7 @@ int cpu_exec(CPUState *env)
 #elif defined(TARGET_ARM)
 #elif defined(TARGET_UNICORE32)
 #elif defined(TARGET_PPC)
+    env->reserve_addr = -1;
 #elif defined(TARGET_LM32)
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
index abadcffec95975569e946cd0a95aab1452dd3c2f..be86d0c4e63e553e1c546c643846271d08b43ec5 100644 (file)
@@ -3,7 +3,9 @@
 include pci.mak
 CONFIG_SERIAL=y
 CONFIG_I8254=y
+CONFIG_PCKBD=y
 CONFIG_VGA_PCI=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_VMWARE_VGA=y
+CONFIG_IDE_CMD646=y
index 3a224d1e0fe6e02bb9925610e987ac58c4144243..dc69232f10da4be242a97f13d1d0e6422dc12c6e 100644 (file)
@@ -41,6 +41,7 @@ void *load_device_tree(const char *filename_path, int *sizep)
     }
 
     /* Expand to 2x size to give enough room for manipulation.  */
+    dt_size += 10000;
     dt_size *= 2;
     /* First allocate space in qemu for device tree */
     fdt = g_malloc0(dt_size);
@@ -72,38 +73,99 @@ fail:
     return NULL;
 }
 
-int qemu_devtree_setprop(void *fdt, const char *node_path,
-                         const char *property, void *val_array, int size)
+static int findnode_nofail(void *fdt, const char *node_path)
 {
     int offset;
 
     offset = fdt_path_offset(fdt, node_path);
-    if (offset < 0)
-        return offset;
+    if (offset < 0) {
+        fprintf(stderr, "%s Couldn't find node %s: %s\n", __func__, node_path,
+                fdt_strerror(offset));
+        exit(1);
+    }
+
+    return offset;
+}
+
+int qemu_devtree_setprop(void *fdt, const char *node_path,
+                         const char *property, void *val_array, int size)
+{
+    int r;
+
+    r = fdt_setprop(fdt, findnode_nofail(fdt, node_path), property, val_array, size);
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't set %s/%s: %s\n", __func__, node_path,
+                property, fdt_strerror(r));
+        exit(1);
+    }
 
-    return fdt_setprop(fdt, offset, property, val_array, size);
+    return r;
 }
 
 int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
                               const char *property, uint32_t val)
 {
-    int offset;
+    int r;
 
-    offset = fdt_path_offset(fdt, node_path);
-    if (offset < 0)
-        return offset;
+    r = fdt_setprop_cell(fdt, findnode_nofail(fdt, node_path), property, val);
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't set %s/%s = %#08x: %s\n", __func__,
+                node_path, property, val, fdt_strerror(r));
+        exit(1);
+    }
 
-    return fdt_setprop_cell(fdt, offset, property, val);
+    return r;
 }
 
 int qemu_devtree_setprop_string(void *fdt, const char *node_path,
                                 const char *property, const char *string)
 {
-    int offset;
+    int r;
 
-    offset = fdt_path_offset(fdt, node_path);
-    if (offset < 0)
-        return offset;
+    r = fdt_setprop_string(fdt, findnode_nofail(fdt, node_path), property, string);
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't set %s/%s = %s: %s\n", __func__,
+                node_path, property, string, fdt_strerror(r));
+        exit(1);
+    }
+
+    return r;
+}
+
+int qemu_devtree_nop_node(void *fdt, const char *node_path)
+{
+    int r;
+
+    r = fdt_nop_node(fdt, findnode_nofail(fdt, node_path));
+    if (r < 0) {
+        fprintf(stderr, "%s: Couldn't nop node %s: %s\n", __func__, node_path,
+                fdt_strerror(r));
+        exit(1);
+    }
+
+    return r;
+}
+
+int qemu_devtree_add_subnode(void *fdt, const char *name)
+{
+    char *dupname = g_strdup(name);
+    char *basename = strrchr(dupname, '/');
+    int retval;
+
+    if (!basename) {
+        return -1;
+    }
+
+    basename[0] = '\0';
+    basename++;
+
+    retval = fdt_add_subnode(fdt, findnode_nofail(fdt, dupname), basename);
+    if (retval < 0) {
+        fprintf(stderr, "FDT: Failed to create subnode %s: %s\n", name,
+                fdt_strerror(retval));
+        exit(1);
+    }
 
-    return fdt_setprop_string(fdt, offset, property, string);
+    g_free(dupname);
+    return retval;
 }
index cecd98f0422ff2483ab823a0e1272051df6d2b5d..4378685b7a9ce3f658a7eeaa4cbad9058fbf33c7 100644 (file)
@@ -22,5 +22,7 @@ int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
                               const char *property, uint32_t val);
 int qemu_devtree_setprop_string(void *fdt, const char *node_path,
                                 const char *property, const char *string);
+int qemu_devtree_nop_node(void *fdt, const char *node_path);
+int qemu_devtree_add_subnode(void *fdt, const char *name);
 
 #endif /* __DEVICE_TREE_H__ */
index 31ecad2556ec40e743d72f50d0d69ee880cf0332..4009058788347ad06d9843d32355b85c44cec594 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -733,7 +733,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
             {
                 if (gdb_has_xml)
                     return 0;
-                GET_REG32(0); /* fpscr */
+                GET_REG32(env->fpscr);
             }
         }
     }
index 07b493ca2770b7b38cbe2ee12971cf5890ec6606..ab08d583df1a5871e6129c2cd54f085915e34539 100644 (file)
@@ -194,7 +194,7 @@ STEXI
 changes status of a trace event
 ETEXI
 
-#if defined(CONFIG_SIMPLE_TRACE)
+#if defined(CONFIG_TRACE_SIMPLE)
     {
         .name       = "trace-file",
         .args_type  = "op:s?,arg:F?",
@@ -1303,7 +1303,7 @@ show i8259 (PIC) state
 @item info pci
 show emulated PCI device info
 @item info tlb
-show virtual to physical memory mappings (i386, SH4 and SPARC only)
+show virtual to physical memory mappings (i386, SH4, SPARC, and PPC only)
 @item info mem
 show the active virtual memory mappings (i386 only)
 @item info jit
index 8dedbf819f76eb5ae0ad63aa2fb7c13189e6df8f..aa15f55dc9a5d58d69d259bf880cf38788be3ef6 100644 (file)
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #include "hw.h"
-#include "ppc_mac.h"
+#include "adb.h"
 #include "console.h"
 
 /* debug ADB */
diff --git a/hw/adb.h b/hw/adb.h
new file mode 100644 (file)
index 0000000..b2a591c
--- /dev/null
+++ b/hw/adb.h
@@ -0,0 +1,67 @@
+/*
+ * QEMU ADB emulation shared definitions and prototypes
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if !defined(__ADB_H__)
+#define __ADB_H__
+
+#define MAX_ADB_DEVICES 16
+
+#define ADB_MAX_OUT_LEN 16
+
+typedef struct ADBDevice ADBDevice;
+
+/* buf = NULL means polling */
+typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out,
+                              const uint8_t *buf, int len);
+typedef int ADBDeviceReset(ADBDevice *d);
+
+struct ADBDevice {
+    struct ADBBusState *bus;
+    int devaddr;
+    int handler;
+    ADBDeviceRequest *devreq;
+    ADBDeviceReset *devreset;
+    void *opaque;
+};
+
+typedef struct ADBBusState {
+    ADBDevice devices[MAX_ADB_DEVICES];
+    int nb_devices;
+    int poll_index;
+} ADBBusState;
+
+int adb_request(ADBBusState *s, uint8_t *buf_out,
+                const uint8_t *buf, int len);
+int adb_poll(ADBBusState *s, uint8_t *buf_out);
+
+ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
+                               ADBDeviceRequest *devreq,
+                               ADBDeviceReset *devreset,
+                               void *opaque);
+void adb_kbd_init(ADBBusState *bus);
+void adb_mouse_init(ADBBusState *bus);
+
+extern ADBBusState adb_bus;
+#endif /* !defined(__ADB_H__) */
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
new file mode 100644 (file)
index 0000000..fcc20e9
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * QEMU Alpha DP264/CLIPPER hardware system emulator.
+ *
+ * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
+ * variants because CLIPPER doesn't have an SMC669 SuperIO controler
+ * that we need to emulate as well.
+ */
+
+#include "hw.h"
+#include "elf.h"
+#include "loader.h"
+#include "boards.h"
+#include "alpha_sys.h"
+#include "sysemu.h"
+#include "mc146818rtc.h"
+#include "ide.h"
+
+#define MAX_IDE_BUS 2
+
+static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
+{
+    if (((addr >> 41) & 3) == 2) {
+        addr &= 0xffffffffffull;
+    }
+    return addr;
+}
+
+/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
+    (0) The dev_irq_n lines into the cpu, which we totally ignore,
+    (1) The DRIR lines in the typhoon chipset,
+    (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
+    (3) The interrupt number assigned by the kernel.
+   The following function is concerned with (1) only.  */
+
+static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
+{
+    int slot = d->devfn >> 3;
+
+    assert(irq_num >= 0 && irq_num <= 3);
+
+    return (slot + 1) * 4 + irq_num;
+}
+
+static void clipper_init(ram_addr_t ram_size,
+                         const char *boot_device,
+                         const char *kernel_filename,
+                         const char *kernel_cmdline,
+                         const char *initrd_filename,
+                         const char *cpu_model)
+{
+    CPUState *cpus[4];
+    PCIBus *pci_bus;
+    qemu_irq rtc_irq;
+    long size, i;
+    const char *palcode_filename;
+    uint64_t palcode_entry, palcode_low, palcode_high;
+    uint64_t kernel_entry, kernel_low, kernel_high;
+
+    /* Create up to 4 cpus.  */
+    memset(cpus, 0, sizeof(cpus));
+    for (i = 0; i < smp_cpus; ++i) {
+        cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
+    }
+
+    cpus[0]->trap_arg0 = ram_size;
+    cpus[0]->trap_arg1 = 0;
+    cpus[0]->trap_arg2 = smp_cpus;
+
+    /* Init the chipset.  */
+    pci_bus = typhoon_init(ram_size, &rtc_irq, cpus, clipper_pci_map_irq);
+
+    rtc_init(1980, rtc_irq);
+    pit_init(0x40, 0);
+    isa_create_simple("i8042");
+
+    /* VGA setup.  Don't bother loading the bios.  */
+    alpha_pci_vga_setup(pci_bus);
+
+    /* Serial code setup.  */
+    for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
+        if (serial_hds[i]) {
+            serial_isa_init(i, serial_hds[i]);
+        }
+    }
+
+    /* Network setup.  e1000 is good enough, failing Tulip support.  */
+    for (i = 0; i < nb_nics; i++) {
+        pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
+    }
+
+    /* IDE disk setup.  */
+    {
+        DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+        ide_drive_get(hd, MAX_IDE_BUS);
+
+        pci_cmd646_ide_init(pci_bus, hd, 0);
+    }
+
+    /* Load PALcode.  Given that this is not "real" cpu palcode,
+       but one explicitly written for the emulation, we might as
+       well load it directly from and ELF image.  */
+    palcode_filename = (bios_name ? bios_name : "palcode-clipper");
+    palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename);
+    if (palcode_filename == NULL) {
+        hw_error("no palcode provided\n");
+        exit(1);
+    }
+    size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
+                    NULL, &palcode_entry, &palcode_low, &palcode_high,
+                    0, EM_ALPHA, 0);
+    if (size < 0) {
+        hw_error("could not load palcode '%s'\n", palcode_filename);
+        exit(1);
+    }
+
+    /* Start all cpus at the PALcode RESET entry point.  */
+    for (i = 0; i < smp_cpus; ++i) {
+        cpus[i]->pal_mode = 1;
+        cpus[i]->pc = palcode_entry;
+        cpus[i]->palbr = palcode_entry;
+    }
+
+    /* Load a kernel.  */
+    if (kernel_filename) {
+        uint64_t param_offset;
+
+        size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
+                        NULL, &kernel_entry, &kernel_low, &kernel_high,
+                        0, EM_ALPHA, 0);
+        if (size < 0) {
+            hw_error("could not load kernel '%s'\n", kernel_filename);
+            exit(1);
+        }
+
+        cpus[0]->trap_arg1 = kernel_entry;
+
+        param_offset = kernel_low - 0x6000;
+
+        if (kernel_cmdline) {
+            pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
+        }
+
+        if (initrd_filename) {
+            long initrd_base, initrd_size;
+
+            initrd_size = get_image_size(initrd_filename);
+            if (initrd_size < 0) {
+                hw_error("could not load initial ram disk '%s'\n",
+                         initrd_filename);
+                exit(1);
+            }
+
+            /* Put the initrd image as high in memory as possible.  */
+            initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
+            load_image_targphys(initrd_filename, initrd_base,
+                                ram_size - initrd_base);
+
+            stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL);
+            stq_phys(param_offset + 0x108, initrd_size);
+        }
+    }
+}
+
+static QEMUMachine clipper_machine = {
+    .name = "clipper",
+    .desc = "Alpha DP264/CLIPPER",
+    .init = clipper_init,
+    .max_cpus = 4,
+    .is_default = 1,
+};
+
+static void clipper_machine_init(void)
+{
+    qemu_register_machine(&clipper_machine);
+}
+
+machine_init(clipper_machine_init);
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
new file mode 100644 (file)
index 0000000..e975702
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * QEMU Alpha PCI support functions.
+ *
+ * Some of this isn't very Alpha specific at all.
+ *
+ * ??? Sparse memory access not implemented.
+ */
+
+#include "config.h"
+#include "alpha_sys.h"
+#include "qemu-log.h"
+#include "sysemu.h"
+#include "vmware_vga.h"
+
+
+/* PCI IO reads/writes, to byte-word addressable memory.  */
+/* ??? Doesn't handle multiple PCI busses.  */
+
+static uint64_t bw_io_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    switch (size) {
+    case 1:
+        return cpu_inb(addr);
+    case 2:
+        return cpu_inw(addr);
+    case 4:
+        return cpu_inl(addr);
+    }
+    abort();
+}
+
+static void bw_io_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t val, unsigned size)
+{
+    switch (size) {
+    case 1:
+        cpu_outb(addr, val);
+        break;
+    case 2:
+        cpu_outw(addr, val);
+        break;
+    case 4:
+        cpu_outl(addr, val);
+        break;
+    default:
+        abort();
+    }
+}
+
+const MemoryRegionOps alpha_pci_bw_io_ops = {
+    .read = bw_io_read,
+    .write = bw_io_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+/* PCI config space reads/writes, to byte-word addressable memory.  */
+static uint64_t bw_conf1_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
+{
+    PCIBus *b = opaque;
+    return pci_data_read(b, addr, size);
+}
+
+static void bw_conf1_write(void *opaque, target_phys_addr_t addr,
+                           uint64_t val, unsigned size)
+{
+    PCIBus *b = opaque;
+    pci_data_write(b, addr, val, size);
+}
+
+const MemoryRegionOps alpha_pci_conf1_ops = {
+    .read = bw_conf1_read,
+    .write = bw_conf1_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+/* PCI/EISA Interrupt Acknowledge Cycle.  */
+
+static uint64_t iack_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    return pic_read_irq(isa_pic);
+}
+
+static void special_write(void *opaque, target_phys_addr_t addr,
+                          uint64_t val, unsigned size)
+{
+    qemu_log("pci: special write cycle");
+}
+
+const MemoryRegionOps alpha_pci_iack_ops = {
+    .read = iack_read,
+    .write = special_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+\f
+void alpha_pci_vga_setup(PCIBus *pci_bus)
+{
+    switch (vga_interface_type) {
+#ifdef CONFIG_SPICE
+    case VGA_QXL:
+        pci_create_simple(pci_bus, -1, "qxl-vga");
+        return;
+#endif
+    case VGA_CIRRUS:
+        pci_cirrus_vga_init(pci_bus);
+        return;
+    case VGA_VMWARE:
+        if (pci_vmsvga_init(pci_bus)) {
+            return;
+        }
+        break;
+    }
+    /* If VGA is enabled at all, and one of the above didn't work, then
+       fallback to Standard VGA.  */
+    if (vga_interface_type != VGA_NONE) {
+        pci_vga_init(pci_bus);
+    }
+}
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
new file mode 100644 (file)
index 0000000..13f0177
--- /dev/null
@@ -0,0 +1,24 @@
+/* Alpha cores and system support chips.  */
+
+#ifndef HW_ALPHA_H
+#define HW_ALPHA_H 1
+
+#include "pci.h"
+#include "pci_host.h"
+#include "ide.h"
+#include "net.h"
+#include "pc.h"
+#include "usb-ohci.h"
+#include "irq.h"
+
+
+PCIBus *typhoon_init(ram_addr_t, qemu_irq *, CPUState *[4], pci_map_irq_fn);
+
+/* alpha_pci.c.  */
+extern const MemoryRegionOps alpha_pci_bw_io_ops;
+extern const MemoryRegionOps alpha_pci_conf1_ops;
+extern const MemoryRegionOps alpha_pci_iack_ops;
+
+void alpha_pci_vga_setup(PCIBus *pci_bus);
+
+#endif
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
new file mode 100644 (file)
index 0000000..c7608bb
--- /dev/null
@@ -0,0 +1,820 @@
+/*
+ * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation.
+ *
+ * Written by Richard Henderson.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "hw.h"
+#include "devices.h"
+#include "sysemu.h"
+#include "alpha_sys.h"
+#include "exec-memory.h"
+
+
+typedef struct TyphoonCchip {
+    MemoryRegion region;
+    uint64_t misc;
+    uint64_t drir;
+    uint64_t dim[4];
+    uint32_t iic[4];
+    CPUState *cpu[4];
+} TyphoonCchip;
+
+typedef struct TyphoonWindow {
+    uint32_t base_addr;
+    uint32_t mask;
+    uint32_t translated_base_pfn;
+} TyphoonWindow;
+typedef struct TyphoonPchip {
+    MemoryRegion region;
+    MemoryRegion reg_iack;
+    MemoryRegion reg_mem;
+    MemoryRegion reg_io;
+    MemoryRegion reg_conf;
+    uint64_t ctl;
+    TyphoonWindow win[4];
+} TyphoonPchip;
+
+typedef struct TyphoonState {
+    PCIHostState host;
+    TyphoonCchip cchip;
+    TyphoonPchip pchip;
+    MemoryRegion dchip_region;
+    MemoryRegion ram_region;
+
+    /* QEMU emulation state.  */
+    uint32_t latch_tmp;
+} TyphoonState;
+
+/* Called when one of DRIR or DIM changes.  */
+static void cpu_irq_change(CPUState *env, uint64_t req)
+{
+    /* If there are any non-masked interrupts, tell the cpu.  */
+    if (env) {
+        if (req) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+    }
+}
+
+static uint64_t cchip_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    CPUState *env = cpu_single_env;
+    TyphoonState *s = opaque;
+    uint64_t ret = 0;
+
+    if (addr & 4) {
+        return s->latch_tmp;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* CSC: Cchip System Configuration Register.  */
+        /* All sorts of data here; probably the only thing relevant is
+           PIP<14> Pchip 1 Present = 0.  */
+        break;
+
+    case 0x0040:
+        /* MTR: Memory Timing Register.  */
+        /* All sorts of stuff related to real DRAM.  */
+        break;
+
+    case 0x0080:
+        /* MISC: Miscellaneous Register.  */
+        ret = s->cchip.misc | (env->cpu_index & 3);
+        break;
+
+    case 0x00c0:
+        /* MPD: Memory Presence Detect Register.  */
+        break;
+
+    case 0x0100: /* AAR0 */
+    case 0x0140: /* AAR1 */
+    case 0x0180: /* AAR2 */
+    case 0x01c0: /* AAR3 */
+        /* AAR: Array Address Register.  */
+        /* All sorts of information about DRAM.  */
+        break;
+
+    case 0x0200:
+        /* DIM0: Device Interrupt Mask Register, CPU0.  */
+        ret = s->cchip.dim[0];
+        break;
+    case 0x0240:
+        /* DIM1: Device Interrupt Mask Register, CPU1.  */
+        ret = s->cchip.dim[1];
+        break;
+    case 0x0280:
+        /* DIR0: Device Interrupt Request Register, CPU0.  */
+        ret = s->cchip.dim[0] & s->cchip.drir;
+        break;
+    case 0x02c0:
+        /* DIR1: Device Interrupt Request Register, CPU1.  */
+        ret = s->cchip.dim[1] & s->cchip.drir;
+        break;
+    case 0x0300:
+        /* DRIR: Device Raw Interrupt Request Register.  */
+        ret = s->cchip.drir;
+        break;
+
+    case 0x0340:
+        /* PRBEN: Probe Enable Register.  */
+        break;
+
+    case 0x0380:
+        /* IIC0: Interval Ignore Count Register, CPU0.  */
+        ret = s->cchip.iic[0];
+        break;
+    case 0x03c0:
+        /* IIC1: Interval Ignore Count Register, CPU1.  */
+        ret = s->cchip.iic[1];
+        break;
+
+    case 0x0400: /* MPR0 */
+    case 0x0440: /* MPR1 */
+    case 0x0480: /* MPR2 */
+    case 0x04c0: /* MPR3 */
+        /* MPR: Memory Programming Register.  */
+        break;
+
+    case 0x0580:
+        /* TTR: TIGbus Timing Register.  */
+        /* All sorts of stuff related to interrupt delivery timings.  */
+        break;
+    case 0x05c0:
+        /* TDR: TIGbug Device Timing Register.  */
+        break;
+
+    case 0x0600:
+        /* DIM2: Device Interrupt Mask Register, CPU2.  */
+        ret = s->cchip.dim[2];
+        break;
+    case 0x0640:
+        /* DIM3: Device Interrupt Mask Register, CPU3.  */
+        ret = s->cchip.dim[3];
+        break;
+    case 0x0680:
+        /* DIR2: Device Interrupt Request Register, CPU2.  */
+        ret = s->cchip.dim[2] & s->cchip.drir;
+        break;
+    case 0x06c0:
+        /* DIR3: Device Interrupt Request Register, CPU3.  */
+        ret = s->cchip.dim[3] & s->cchip.drir;
+        break;
+
+    case 0x0700:
+        /* IIC2: Interval Ignore Count Register, CPU2.  */
+        ret = s->cchip.iic[2];
+        break;
+    case 0x0740:
+        /* IIC3: Interval Ignore Count Register, CPU3.  */
+        ret = s->cchip.iic[3];
+        break;
+
+    case 0x0780:
+        /* PWR: Power Management Control.   */
+        break;
+    
+    case 0x0c00: /* CMONCTLA */
+    case 0x0c40: /* CMONCTLB */
+    case 0x0c80: /* CMONCNT01 */
+    case 0x0cc0: /* CMONCNT23 */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
+        return -1;
+    }
+
+    s->latch_tmp = ret >> 32;
+    return ret;
+}
+
+static uint64_t dchip_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    /* Skip this.  It's all related to DRAM timing and setup.  */
+    return 0;
+}
+
+static uint64_t pchip_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    TyphoonState *s = opaque;
+    uint64_t ret = 0;
+
+    if (addr & 4) {
+        return s->latch_tmp;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* WSBA0: Window Space Base Address Register.  */
+        ret = s->pchip.win[0].base_addr;
+        break;
+    case 0x0040:
+        /* WSBA1 */
+        ret = s->pchip.win[1].base_addr;
+        break;
+    case 0x0080:
+        /* WSBA2 */
+        ret = s->pchip.win[2].base_addr;
+        break;
+    case 0x00c0:
+        /* WSBA3 */
+        ret = s->pchip.win[3].base_addr;
+        break;
+
+    case 0x0100:
+        /* WSM0: Window Space Mask Register.  */
+        ret = s->pchip.win[0].mask;
+        break;
+    case 0x0140:
+        /* WSM1 */
+        ret = s->pchip.win[1].mask;
+        break;
+    case 0x0180:
+        /* WSM2 */
+        ret = s->pchip.win[2].mask;
+        break;
+    case 0x01c0:
+        /* WSM3 */
+        ret = s->pchip.win[3].mask;
+        break;
+
+    case 0x0200:
+        /* TBA0: Translated Base Address Register.  */
+        ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
+        break;
+    case 0x0240:
+        /* TBA1 */
+        ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
+        break;
+    case 0x0280:
+        /* TBA2 */
+        ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
+        break;
+    case 0x02c0:
+        /* TBA3 */
+        ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
+        break;
+
+    case 0x0300:
+        /* PCTL: Pchip Control Register.  */
+        ret = s->pchip.ctl;
+        break;
+    case 0x0340:
+        /* PLAT: Pchip Master Latency Register.  */
+        break;
+    case 0x03c0:
+        /* PERROR: Pchip Error Register.  */
+        break;
+    case 0x0400:
+        /* PERRMASK: Pchip Error Mask Register.  */
+        break;
+    case 0x0440:
+        /* PERRSET: Pchip Error Set Register.  */
+        break;
+    case 0x0480:
+        /* TLBIV: Translation Buffer Invalidate Virtual Register (WO).  */
+        break;
+    case 0x04c0:
+        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
+        break;
+    case 0x0500: /* PMONCTL */
+    case 0x0540: /* PMONCNT */
+    case 0x0800: /* SPRST */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
+        return -1;
+    }
+
+    s->latch_tmp = ret >> 32;
+    return ret;
+}
+
+static void cchip_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t v32, unsigned size)
+{
+    TyphoonState *s = opaque;
+    uint64_t val, oldval, newval;
+
+    if (addr & 4) {
+        val = v32 << 32 | s->latch_tmp;
+        addr ^= 4;
+    } else {
+        s->latch_tmp = v32;
+        return;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* CSC: Cchip System Configuration Register.  */
+        /* All sorts of data here; nothing relevant RW.  */
+        break;
+
+    case 0x0040:
+        /* MTR: Memory Timing Register.  */
+        /* All sorts of stuff related to real DRAM.  */
+        break;
+
+    case 0x0080:
+        /* MISC: Miscellaneous Register.  */
+        newval = oldval = s->cchip.misc;
+        newval &= ~(val & 0x10000ff0);     /* W1C fields */
+        if (val & 0x100000) {
+            newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */
+        } else {
+            newval |= val & 0x00f00000;    /* ABT field is W1S */
+            if ((newval & 0xf0000) == 0) {
+                newval |= val & 0xf0000;   /* ABW field is W1S iff zero */
+            }
+        }
+        newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */
+
+        newval &= ~0xf0000000000ull;       /* WO and RW fields */
+        newval |= val & 0xf0000000000ull;
+        s->cchip.misc = newval;
+
+        /* Pass on changes to IPI and ITI state.  */
+        if ((newval ^ oldval) & 0xff0) {
+            int i;
+            for (i = 0; i < 4; ++i) {
+                CPUState *env = s->cchip.cpu[i];
+                if (env) {
+                    /* IPI can be either cleared or set by the write.  */
+                    if (newval & (1 << (i + 8))) {
+                        cpu_interrupt(env, CPU_INTERRUPT_SMP);
+                    } else {
+                        cpu_reset_interrupt(env, CPU_INTERRUPT_SMP);
+                    }
+
+                    /* ITI can only be cleared by the write.  */
+                    if ((newval & (1 << (i + 4))) == 0) {
+                        cpu_reset_interrupt(env, CPU_INTERRUPT_TIMER);
+                    }
+                }
+            }
+        }
+        break;
+
+    case 0x00c0:
+        /* MPD: Memory Presence Detect Register.  */
+        break;
+
+    case 0x0100: /* AAR0 */
+    case 0x0140: /* AAR1 */
+    case 0x0180: /* AAR2 */
+    case 0x01c0: /* AAR3 */
+        /* AAR: Array Address Register.  */
+        /* All sorts of information about DRAM.  */
+        break;
+
+    case 0x0200: /* DIM0 */
+        /* DIM: Device Interrupt Mask Register, CPU0.  */
+        s->cchip.dim[0] = val;
+        cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
+        break;
+    case 0x0240: /* DIM1 */
+        /* DIM: Device Interrupt Mask Register, CPU1.  */
+        s->cchip.dim[0] = val;
+        cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
+        break;
+
+    case 0x0280: /* DIR0 (RO) */
+    case 0x02c0: /* DIR1 (RO) */
+    case 0x0300: /* DRIR (RO) */
+        break;
+
+    case 0x0340:
+        /* PRBEN: Probe Enable Register.  */
+        break;
+
+    case 0x0380: /* IIC0 */
+        s->cchip.iic[0] = val & 0xffffff;
+        break;
+    case 0x03c0: /* IIC1 */
+        s->cchip.iic[1] = val & 0xffffff;
+        break;
+
+    case 0x0400: /* MPR0 */
+    case 0x0440: /* MPR1 */
+    case 0x0480: /* MPR2 */
+    case 0x04c0: /* MPR3 */
+        /* MPR: Memory Programming Register.  */
+        break;
+
+    case 0x0580:
+        /* TTR: TIGbus Timing Register.  */
+        /* All sorts of stuff related to interrupt delivery timings.  */
+        break;
+    case 0x05c0:
+        /* TDR: TIGbug Device Timing Register.  */
+        break;
+
+    case 0x0600:
+        /* DIM2: Device Interrupt Mask Register, CPU2.  */
+        s->cchip.dim[2] = val;
+        cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
+        break;
+    case 0x0640:
+        /* DIM3: Device Interrupt Mask Register, CPU3.  */
+        s->cchip.dim[3] = val;
+        cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
+        break;
+
+    case 0x0680: /* DIR2 (RO) */
+    case 0x06c0: /* DIR3 (RO) */
+        break;
+
+    case 0x0700: /* IIC2 */
+        s->cchip.iic[2] = val & 0xffffff;
+        break;
+    case 0x0740: /* IIC3 */
+        s->cchip.iic[3] = val & 0xffffff;
+        break;
+
+    case 0x0780:
+        /* PWR: Power Management Control.   */
+        break;
+    
+    case 0x0c00: /* CMONCTLA */
+    case 0x0c40: /* CMONCTLB */
+    case 0x0c80: /* CMONCNT01 */
+    case 0x0cc0: /* CMONCNT23 */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
+        return;
+    }
+}
+
+static void dchip_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t val, unsigned size)
+{
+    /* Skip this.  It's all related to DRAM timing and setup.  */
+}
+
+static void pchip_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t v32, unsigned size)
+{
+    TyphoonState *s = opaque;
+    uint64_t val, oldval;
+
+    if (addr & 4) {
+        val = v32 << 32 | s->latch_tmp;
+        addr ^= 4;
+    } else {
+        s->latch_tmp = v32;
+        return;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* WSBA0: Window Space Base Address Register.  */
+        s->pchip.win[0].base_addr = val;
+        break;
+    case 0x0040:
+        /* WSBA1 */
+        s->pchip.win[1].base_addr = val;
+        break;
+    case 0x0080:
+        /* WSBA2 */
+        s->pchip.win[2].base_addr = val;
+        break;
+    case 0x00c0:
+        /* WSBA3 */
+        s->pchip.win[3].base_addr = val;
+        break;
+
+    case 0x0100:
+        /* WSM0: Window Space Mask Register.  */
+        s->pchip.win[0].mask = val;
+        break;
+    case 0x0140:
+        /* WSM1 */
+        s->pchip.win[1].mask = val;
+        break;
+    case 0x0180:
+        /* WSM2 */
+        s->pchip.win[2].mask = val;
+        break;
+    case 0x01c0:
+        /* WSM3 */
+        s->pchip.win[3].mask = val;
+        break;
+
+    case 0x0200:
+        /* TBA0: Translated Base Address Register.  */
+        s->pchip.win[0].translated_base_pfn = val >> 10;
+        break;
+    case 0x0240:
+        /* TBA1 */
+        s->pchip.win[1].translated_base_pfn = val >> 10;
+        break;
+    case 0x0280:
+        /* TBA2 */
+        s->pchip.win[2].translated_base_pfn = val >> 10;
+        break;
+    case 0x02c0:
+        /* TBA3 */
+        s->pchip.win[3].translated_base_pfn = val >> 10;
+        break;
+
+    case 0x0300:
+        /* PCTL: Pchip Control Register.  */
+        oldval = s->pchip.ctl;
+        oldval &= ~0x00001cff0fc7ffull;       /* RW fields */
+        oldval |= val & 0x00001cff0fc7ffull;
+
+        s->pchip.ctl = oldval;
+        break;
+
+    case 0x0340:
+        /* PLAT: Pchip Master Latency Register.  */
+        break;
+    case 0x03c0:
+        /* PERROR: Pchip Error Register.  */
+        break;
+    case 0x0400:
+        /* PERRMASK: Pchip Error Mask Register.  */
+        break;
+    case 0x0440:
+        /* PERRSET: Pchip Error Set Register.  */
+        break;
+
+    case 0x0480:
+        /* TLBIV: Translation Buffer Invalidate Virtual Register.  */
+        break;
+
+    case 0x04c0:
+        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
+        break;
+
+    case 0x0500:
+        /* PMONCTL */
+    case 0x0540:
+        /* PMONCNT */
+    case 0x0800:
+        /* SPRST */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
+        return;
+    }
+}
+
+static const MemoryRegionOps cchip_ops = {
+    .read = cchip_read,
+    .write = cchip_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,  /* ??? Should be 8.  */
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static const MemoryRegionOps dchip_ops = {
+    .read = dchip_read,
+    .write = dchip_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,  /* ??? Should be 8.  */
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+};
+
+static const MemoryRegionOps pchip_ops = {
+    .read = pchip_read,
+    .write = pchip_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,  /* ??? Should be 8.  */
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void typhoon_set_irq(void *opaque, int irq, int level)
+{
+    TyphoonState *s = opaque;
+    uint64_t drir;
+    int i;
+
+    /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL.  */
+    drir = s->cchip.drir;
+    if (level) {
+        drir |= 1ull << irq;
+    } else {
+        drir &= ~(1ull << irq);
+    }
+    s->cchip.drir = drir;
+
+    for (i = 0; i < 4; ++i) {
+        cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
+    }
+}
+
+static void typhoon_set_isa_irq(void *opaque, int irq, int level)
+{
+    typhoon_set_irq(opaque, 55, level);
+}
+
+static void typhoon_set_timer_irq(void *opaque, int irq, int level)
+{
+    TyphoonState *s = opaque;
+    int i;
+
+    /* Thankfully, the mc146818rtc code doesn't track the IRQ state,
+       and so we don't have to worry about missing interrupts just
+       because we never actually ACK the interrupt.  Just ignore any
+       case of the interrupt level going low.  */
+    if (level == 0) {
+        return;
+    }
+
+    /* Deliver the interrupt to each CPU, considering each CPU's IIC.  */
+    for (i = 0; i < 4; ++i) {
+        CPUState *env = s->cchip.cpu[i];
+        if (env) {
+            uint32_t iic = s->cchip.iic[i];
+
+            /* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
+               Bit 24 is the OverFlow bit, RO, and set when the count
+               decrements past 0.  When is OF cleared?  My guess is that
+               OF is actually cleared when the IIC is written, and that
+               the ICNT field always decrements.  At least, that's an
+               interpretation that makes sense, and "allows the CPU to
+               determine exactly how mant interval timer ticks were
+               skipped".  At least within the next 4M ticks...  */
+
+            iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
+            s->cchip.iic[i] = iic;
+
+            if (iic & 0x1000000) {
+                /* Set the ITI bit for this cpu.  */
+                s->cchip.misc |= 1 << (i + 4);
+                /* And signal the interrupt.  */
+                cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+            }
+        }
+    }
+}
+
+static void typhoon_alarm_timer(void *opaque)
+{
+    TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
+    int cpu = (uintptr_t)opaque & 3;
+
+    /* Set the ITI bit for this cpu.  */
+    s->cchip.misc |= 1 << (cpu + 4);
+    cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER);
+}
+
+PCIBus *typhoon_init(ram_addr_t ram_size, qemu_irq *p_rtc_irq,
+                     CPUState *cpus[4], pci_map_irq_fn sys_map_irq)
+{
+    const uint64_t MB = 1024 * 1024;
+    const uint64_t GB = 1024 * MB;
+    MemoryRegion *addr_space = get_system_memory();
+    MemoryRegion *addr_space_io = get_system_io();
+    DeviceState *dev;
+    PCIHostState *p;
+    TyphoonState *s;
+    PCIBus *b;
+    int i;
+
+    dev = qdev_create(NULL, "typhoon-pcihost");
+    qdev_init_nofail(dev);
+
+    p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+    s = container_of(p, TyphoonState, host);
+
+    /* Remember the CPUs so that we can deliver interrupts to them.  */
+    for (i = 0; i < 4; i++) {
+        CPUState *env = cpus[i];
+        s->cchip.cpu[i] = env;
+        if (env) {
+            env->alarm_timer = qemu_new_timer_ns(rtc_clock,
+                                                 typhoon_alarm_timer,
+                                                 (void *)((uintptr_t)s + i));
+        }
+    }
+
+    *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
+
+    /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
+       but the address space hole reserved at this point is 8TB.  */
+    memory_region_init_ram(&s->ram_region, NULL, "ram", ram_size);
+    memory_region_add_subregion(addr_space, 0, &s->ram_region);
+
+    /* TIGbus, 0x801.0000.0000, 1GB.  */
+    /* ??? The TIGbus is used for delivering interrupts, and access to
+       the flash ROM.  I'm not sure that we need to implement it at all.  */
+
+    /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
+    memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB);
+    memory_region_add_subregion(addr_space, 0x80180000000ULL,
+                                &s->pchip.region);
+
+    /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
+    memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB);
+    memory_region_add_subregion(addr_space, 0x801a0000000ULL,
+                                &s->cchip.region);
+
+    /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
+    memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB);
+    memory_region_add_subregion(addr_space, 0x801b0000000ULL,
+                                &s->dchip_region);
+
+    /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
+    memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB);
+    memory_region_add_subregion(addr_space, 0x80000000000ULL,
+                                &s->pchip.reg_mem);
+
+    /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
+    /* ??? Ideally we drop the "system" i/o space on the floor and give the
+       PCI subsystem the full address space reserved by the chipset.
+       We can't do that until the MEM and IO paths in memory.c are unified.  */
+    memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL,
+                          "pci0-io", 32*MB);
+    memory_region_add_subregion(addr_space, 0x801fc000000ULL,
+                                &s->pchip.reg_io);
+
+    b = pci_register_bus(&s->host.busdev.qdev, "pci",
+                         typhoon_set_irq, sys_map_irq, s,
+                         &s->pchip.reg_mem, addr_space_io, 0, 64);
+    s->host.bus = b;
+
+    /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
+    memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
+                          "pci0-iack", 64*MB);
+    memory_region_add_subregion(addr_space, 0x801f8000000ULL,
+                                &s->pchip.reg_iack);
+
+    /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
+    memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b,
+                          "pci0-conf", 16*MB);
+    memory_region_add_subregion(addr_space, 0x801fe000000ULL,
+                                &s->pchip.reg_conf);
+
+    /* For the record, these are the mappings for the second PCI bus.
+       We can get away with not implementing them because we indicate
+       via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
+    /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
+    /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
+    /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
+    /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
+    /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */
+
+    /* Init the ISA bus.  */
+    /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
+    {
+        qemu_irq isa_pci_irq, *isa_irqs;
+
+        isa_bus_new(NULL, addr_space_io);
+        isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
+        isa_irqs = i8259_init(isa_pci_irq);
+        isa_bus_irqs(isa_irqs);
+    }
+
+    return b;
+}
+
+static int typhoon_pcihost_init(SysBusDevice *dev)
+{
+    return 0;
+}
+
+static SysBusDeviceInfo typhoon_pcihost_info = {
+    .init = typhoon_pcihost_init,
+    .qdev.name = "typhoon-pcihost",
+    .qdev.size = sizeof(TyphoonState),
+    .qdev.no_user = 1
+};
+
+static void typhoon_register(void)
+{
+    sysbus_register_withprop(&typhoon_pcihost_info);
+}
+device_init(typhoon_register);
index e16665e1960cca6c07d164ef9811c7b1bd4852f2..a7e03a313ceaaecebf84fe668e1ec750925a7b0a 100644 (file)
@@ -346,7 +346,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
     }
 }
 
-static uint64_t cs_read(void *opaque, target_phys_addr_t addr, unsigned size)
+static uint64_t cs_read (void *opaque, target_phys_addr_t addr, unsigned size)
 {
     CSState *s = opaque;
     uint32_t saddr, iaddr, ret;
@@ -383,8 +383,8 @@ static uint64_t cs_read(void *opaque, target_phys_addr_t addr, unsigned size)
     return ret;
 }
 
-static void cs_write(void *opaque, target_phys_addr_t addr,
-                     uint64_t val64, unsigned size)
+static void cs_write (void *opaque, target_phys_addr_t addr,
+                      uint64_t val64, unsigned size)
 {
     CSState *s = opaque;
     uint32_t saddr, iaddr, val;
@@ -647,8 +647,8 @@ static int cs4231a_initfn (ISADevice *dev)
 
     isa_init_irq (dev, &s->pic, s->irq);
 
-    memory_region_init_io(&s->ioports, &cs_ioport_ops, s, "cs4231a", 4);
-    isa_register_ioport(dev, &s->ioports, s->port);
+    memory_region_init_io (&s->ioports, &cs_ioport_ops, s, "cs4231a", 4);
+    isa_register_ioport (dev, &s->ioports, s->port);
 
     DMA_register_channel (s->dma, cs_dma_read, s);
 
index 5c92d81b4b2af5d82b25e053bc8a6f027b83b691..40774360df4bacc34e9e4cef3f8a894683a5f9ae 100644 (file)
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -24,6 +24,7 @@
  */
 #include "hw.h"
 #include "ppc_mac.h"
+#include "adb.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
 
@@ -633,16 +634,20 @@ static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static CPUWriteMemoryFunc * const cuda_write[] = {
-    &cuda_writeb,
-    &cuda_writew,
-    &cuda_writel,
-};
-
-static CPUReadMemoryFunc * const cuda_read[] = {
-    &cuda_readb,
-    &cuda_readw,
-    &cuda_readl,
+static MemoryRegionOps cuda_ops = {
+    .old_mmio = {
+        .write = {
+            cuda_writeb,
+            cuda_writew,
+            cuda_writel,
+        },
+        .read = {
+            cuda_readb,
+            cuda_readw,
+            cuda_readl,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static bool cuda_timer_exist(void *opaque, int version_id)
@@ -739,8 +744,8 @@ void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq)
     s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
 
     s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
-    cpu_register_io_memory(cuda_read, cuda_write, s,
-                                             DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000);
+
     *cuda_mem = &s->mem;
     vmstate_register(NULL, -1, &vmstate_cuda, s);
     qemu_register_reset(cuda_reset, s);
index 07fda83169d6c558216a9876ae05f8d78a929163..8ac384ff2031bae786a92bec95a24736642febad 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef QEMU_DEVICES_H
 #define QEMU_DEVICES_H
 
+/* ??? Not all users of this file can include cpu-common.h.  */
+struct MemoryRegion;
+
 /* Devices that have nowhere better to go.  */
 
 /* smc91c111.c */
@@ -57,7 +60,8 @@ qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s);
 qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
 
 /* sm501.c */
-void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
+void sm501_init(struct MemoryRegion *address_space_mem, uint32_t base,
+                uint32_t local_mem_bytes, qemu_irq irq,
                 CharDriverState *chr);
 
 #endif
index 5ca8253ae23f80d1346be8832337a4070f3bd34e..02d01836ceaec2de9fdaf81a5a4f5f86de40004a 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <sys/time.h>
 #include "hw.h"
+#include "exec-memory.h"
 #include "qemu-common.h"
 #include "sysemu.h"
 
@@ -185,7 +186,7 @@ struct fs_dma_channel
 
 struct fs_dma_ctrl
 {
-       int map;
+       MemoryRegion mmio;
        int nr_channels;
        struct fs_dma_channel *channels;
 
@@ -562,13 +563,17 @@ static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr)
         return 0;
 }
 
-static uint32_t
-dma_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t
+dma_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
         struct fs_dma_ctrl *ctrl = opaque;
        int c;
        uint32_t r = 0;
 
+       if (size != 4) {
+               dma_rinvalid(opaque, addr);
+       }
+
        /* Make addr relative to this channel and bounded to nr regs.  */
        c = fs_channel(addr);
        addr &= 0xff;
@@ -606,11 +611,17 @@ dma_update_state(struct fs_dma_ctrl *ctrl, int c)
 }
 
 static void
-dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+dma_write(void *opaque, target_phys_addr_t addr,
+         uint64_t val64, unsigned int size)
 {
         struct fs_dma_ctrl *ctrl = opaque;
+       uint32_t value = val64;
        int c;
 
+       if (size != 4) {
+               dma_winvalid(opaque, addr, value);
+       }
+
         /* Make addr relative to this channel and bounded to nr regs.  */
        c = fs_channel(addr);
         addr &= 0xff;
@@ -666,16 +677,14 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
         }
 }
 
-static CPUReadMemoryFunc * const dma_read[] = {
-       &dma_rinvalid,
-       &dma_rinvalid,
-       &dma_readl,
-};
-
-static CPUWriteMemoryFunc * const dma_write[] = {
-       &dma_winvalid,
-       &dma_winvalid,
-       &dma_writel,
+static const MemoryRegionOps dma_ops = {
+       .read = dma_read,
+       .write = dma_write,
+       .endianness = DEVICE_NATIVE_ENDIAN,
+       .valid = {
+               .min_access_size = 1,
+               .max_access_size = 4
+       }
 };
 
 static int etraxfs_dmac_run(void *opaque)
@@ -748,7 +757,9 @@ void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels)
        ctrl->nr_channels = nr_channels;
        ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
 
-       ctrl->map = cpu_register_io_memory(dma_read, dma_write, ctrl, DEVICE_NATIVE_ENDIAN);
-       cpu_register_physical_memory(base, nr_channels * 0x2000, ctrl->map);
+       memory_region_init_io(&ctrl->mmio, &dma_ops, ctrl, "etraxfs-dma",
+                             nr_channels * 0x2000);
+       memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
+
        return ctrl;
 }
index 48de6dcd47d968d52dea92d987feb7558be2d5fd..246a279b206e0253f2ba36bebcb352a57fa27e71 100644 (file)
@@ -320,6 +320,7 @@ static void mdio_cycle(struct qemu_mdio *bus)
 struct fs_eth
 {
        SysBusDevice busdev;
+       MemoryRegion mmio;
        NICState *nic;
        NICConf conf;
        int ethregs;
@@ -373,7 +374,8 @@ static void eth_validate_duplex(struct fs_eth *eth)
        }
 }
 
-static uint32_t eth_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t
+eth_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
        struct fs_eth *eth = opaque;
        uint32_t r = 0;
@@ -417,9 +419,11 @@ static void eth_update_ma(struct fs_eth *eth, int ma)
 }
 
 static void
-eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+eth_write(void *opaque, target_phys_addr_t addr,
+          uint64_t val64, unsigned int size)
 {
        struct fs_eth *eth = opaque;
+       uint32_t value = val64;
 
        addr >>= 2;
        switch (addr)
@@ -553,14 +557,14 @@ static void eth_set_link(VLANClientState *nc)
        eth->phy.link = !nc->link_down;
 }
 
-static CPUReadMemoryFunc * const eth_read[] = {
-       NULL, NULL,
-       &eth_readl,
-};
-
-static CPUWriteMemoryFunc * const eth_write[] = {
-       NULL, NULL,
-       &eth_writel,
+static const MemoryRegionOps eth_ops = {
+       .read = eth_read,
+       .write = eth_write,
+       .endianness = DEVICE_LITTLE_ENDIAN,
+       .valid = {
+               .min_access_size = 4,
+               .max_access_size = 4
+       }
 };
 
 static void eth_cleanup(VLANClientState *nc)
@@ -589,7 +593,6 @@ static NetClientInfo net_etraxfs_info = {
 static int fs_eth_init(SysBusDevice *dev)
 {
        struct fs_eth *s = FROM_SYSBUS(typeof(*s), dev);
-       int eth_regs;
 
        if (!s->dma_out || !s->dma_in) {
                hw_error("Unconnected ETRAX-FS Ethernet MAC.\n");
@@ -600,9 +603,8 @@ static int fs_eth_init(SysBusDevice *dev)
        s->dma_in->client.opaque = s;
        s->dma_in->client.pull = NULL;
 
-       eth_regs = cpu_register_io_memory(eth_read, eth_write, s,
-                                         DEVICE_LITTLE_ENDIAN);
-       sysbus_init_mmio(dev, 0x5c, eth_regs);
+       memory_region_init_io(&s->mmio, &eth_ops, s, "etraxfs-eth", 0x5c);
+       sysbus_init_mmio_region(dev, &s->mmio);
 
        qemu_macaddr_default_if_unset(&s->conf.macaddr);
        s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
index 4feffda6083da160fd6c8426a5315a24757e4a3a..47a56d753c66baf172ccca29d2c9ea685da78ea5 100644 (file)
@@ -39,6 +39,7 @@
 struct etrax_pic
 {
     SysBusDevice busdev;
+    MemoryRegion mmio;
     void *interrupt_vector;
     qemu_irq parent_irq;
     qemu_irq parent_nmi;
@@ -77,7 +78,8 @@ static void pic_update(struct etrax_pic *fs)
     qemu_set_irq(fs->parent_irq, !!vector);
 }
 
-static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t
+pic_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
     struct etrax_pic *fs = opaque;
     uint32_t rval;
@@ -87,8 +89,8 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
     return rval;
 }
 
-static void
-pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+static void pic_write(void *opaque, target_phys_addr_t addr,
+                      uint64_t value, unsigned int size)
 {
     struct etrax_pic *fs = opaque;
     D(printf("%s addr=%x val=%x\n", __func__, addr, value));
@@ -99,14 +101,14 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const pic_read[] = {
-    NULL, NULL,
-    &pic_readl,
-};
-
-static CPUWriteMemoryFunc * const pic_write[] = {
-    NULL, NULL,
-    &pic_writel,
+static const MemoryRegionOps pic_ops = {
+    .read = pic_read,
+    .write = pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
 };
 
 static void nmi_handler(void *opaque, int irq, int level)
@@ -139,15 +141,13 @@ static void irq_handler(void *opaque, int irq, int level)
 static int etraxfs_pic_init(SysBusDevice *dev)
 {
     struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
-    int intr_vect_regs;
 
     qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_nmi);
 
-    intr_vect_regs = cpu_register_io_memory(pic_read, pic_write, s,
-                                            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
+    memory_region_init_io(&s->mmio, &pic_ops, s, "etraxfs-pic", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->mmio);
     return 0;
 }
 
index 00360371e3c4a5170d660c58434c83106b973834..298b9857ca47ba687b5f46e7d8756e55feb09a14 100644 (file)
@@ -47,6 +47,7 @@
 struct etrax_serial
 {
     SysBusDevice busdev;
+    MemoryRegion mmio;
     CharDriverState *chr;
     qemu_irq irq;
 
@@ -73,7 +74,8 @@ static void ser_update_irq(struct etrax_serial *s)
     qemu_set_irq(s->irq, !!s->regs[R_MASKED_INTR]);
 }
 
-static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t
+ser_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
     struct etrax_serial *s = opaque;
     D(CPUState *env = s->env);
@@ -108,10 +110,12 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
 }
 
 static void
-ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+ser_write(void *opaque, target_phys_addr_t addr,
+          uint64_t val64, unsigned int size)
 {
     struct etrax_serial *s = opaque;
-    unsigned char ch = value;
+    uint32_t value = val64;
+    unsigned char ch = val64;
     D(CPUState *env = s->env);
 
     D(qemu_log("%s " TARGET_FMT_plx "=%x\n",  __func__, addr, value));
@@ -142,14 +146,14 @@ ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     ser_update_irq(s);
 }
 
-static CPUReadMemoryFunc * const ser_read[] = {
-    NULL, NULL,
-    &ser_readl,
-};
-
-static CPUWriteMemoryFunc * const ser_write[] = {
-    NULL, NULL,
-    &ser_writel,
+static const MemoryRegionOps ser_ops = {
+    .read = ser_read,
+    .write = ser_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
 };
 
 static void serial_receive(void *opaque, const uint8_t *buf, int size)
@@ -207,12 +211,11 @@ static void etraxfs_ser_reset(DeviceState *d)
 static int etraxfs_ser_init(SysBusDevice *dev)
 {
     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
-    int ser_regs;
 
     sysbus_init_irq(dev, &s->irq);
-    ser_regs = cpu_register_io_memory(ser_read, ser_write, s,
-                                      DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
+    memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->mmio);
+
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr)
         qemu_chr_add_handlers(s->chr,
index b08e57415da2e6e9f7af0f469ce3ff4c3c2d46c2..57dc7397101e599b554dbf7f8a05c0a11600f6d9 100644 (file)
@@ -43,6 +43,7 @@
 
 struct etrax_timer {
     SysBusDevice busdev;
+    MemoryRegion mmio;
     qemu_irq irq;
     qemu_irq nmi;
 
@@ -72,7 +73,8 @@ struct etrax_timer {
     uint32_t r_masked_intr;
 };
 
-static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
+static uint64_t
+timer_read(void *opaque, target_phys_addr_t addr, unsigned int size)
 {
     struct etrax_timer *t = opaque;
     uint32_t r = 0;
@@ -239,9 +241,11 @@ static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value)
 }
 
 static void
-timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+timer_write(void *opaque, target_phys_addr_t addr,
+            uint64_t val64, unsigned int size)
 {
     struct etrax_timer *t = opaque;
+    uint32_t value = val64;
 
     switch (addr)
     {
@@ -281,14 +285,14 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const timer_read[] = {
-    NULL, NULL,
-    &timer_readl,
-};
-
-static CPUWriteMemoryFunc * const timer_write[] = {
-    NULL, NULL,
-    &timer_writel,
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
 };
 
 static void etraxfs_timer_reset(void *opaque)
@@ -307,7 +311,6 @@ static void etraxfs_timer_reset(void *opaque)
 static int etraxfs_timer_init(SysBusDevice *dev)
 {
     struct etrax_timer *t = FROM_SYSBUS(typeof (*t), dev);
-    int timer_regs;
 
     t->bh_t0 = qemu_bh_new(timer0_hit, t);
     t->bh_t1 = qemu_bh_new(timer1_hit, t);
@@ -319,10 +322,8 @@ static int etraxfs_timer_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &t->irq);
     sysbus_init_irq(dev, &t->nmi);
 
-    timer_regs = cpu_register_io_memory(timer_read, timer_write, t,
-                                        DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x5c, timer_regs);
-
+    memory_region_init_io(&t->mmio, &timer_ops, t, "etraxfs-timer", 0x5c);
+    sysbus_init_mmio_region(dev, &t->mmio);
     qemu_register_reset(etraxfs_timer_reset, t);
     return 0;
 }
index 1c3425372addbaa5fdd3a985b1f6581a17c8e890..432683aceaf6525b4265b72675af60435d2f8758 100644 (file)
@@ -275,8 +275,9 @@ static void gt64120_isd_mapping(GT64120State *s)
     check_reserved_space(&start, &length);
     length = 0x1000;
     /* Map new address */
-    DPRINTF("ISD: "TARGET_FMT_plx"@"TARGET_FMT_plx" -> "TARGET_FMT_plx"@"TARGET_FMT_plx", %x\n", s->ISD_length, s->ISD_start,
-            length, start, s->ISD_handle);
+    DPRINTF("ISD: "TARGET_FMT_plx"@"TARGET_FMT_plx
+        " -> "TARGET_FMT_plx"@"TARGET_FMT_plx"\n",
+        s->ISD_length, s->ISD_start, length, start);
     s->ISD_start = start;
     s->ISD_length = length;
     memory_region_add_subregion(get_system_memory(), s->ISD_start, &s->ISD_mem);
@@ -543,19 +544,19 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
         /* not really implemented */
         s->regs[saddr] = ~(~(s->regs[saddr]) | ~(val & 0xfffffffe));
         s->regs[saddr] |= !!(s->regs[saddr] & 0xfffffffe);
-        DPRINTF("INTRCAUSE %x\n", val);
+        DPRINTF("INTRCAUSE %" PRIx64 "\n", val);
         break;
     case GT_INTRMASK:
         s->regs[saddr] = val & 0x3c3ffffe;
-        DPRINTF("INTRMASK %x\n", val);
+        DPRINTF("INTRMASK %" PRIx64 "\n", val);
         break;
     case GT_PCI0_ICMASK:
         s->regs[saddr] = val & 0x03fffffe;
-        DPRINTF("ICMASK %x\n", val);
+        DPRINTF("ICMASK %" PRIx64 "\n", val);
         break;
     case GT_PCI0_SERR0MASK:
         s->regs[saddr] = val & 0x0000003f;
-        DPRINTF("SERR0MASK %x\n", val);
+        DPRINTF("SERR0MASK %" PRIx64 "\n", val);
         break;
 
     /* Reserved when only PCI_0 is configured. */
index b8b76f4b87bebe95abc64a39fda88102d9de5182..686a5ed86d74e69bfb50f069fa5c6759a1792ecb 100644 (file)
@@ -38,6 +38,7 @@
 #include "devices.h"
 #include "boards.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 static const int sector_len = 128 * 1024;
 
@@ -49,11 +50,12 @@ static void connex_init(ram_addr_t ram_size,
     PXA2xxState *cpu;
     DriveInfo *dinfo;
     int be;
+    MemoryRegion *address_space_mem = get_system_memory();
 
     uint32_t connex_rom = 0x01000000;
     uint32_t connex_ram = 0x04000000;
 
-    cpu = pxa255_init(connex_ram);
+    cpu = pxa255_init(address_space_mem, connex_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     if (!dinfo) {
@@ -87,11 +89,12 @@ static void verdex_init(ram_addr_t ram_size,
     PXA2xxState *cpu;
     DriveInfo *dinfo;
     int be;
+    MemoryRegion *address_space_mem = get_system_memory();
 
     uint32_t verdex_rom = 0x02000000;
     uint32_t verdex_ram = 0x10000000;
 
-    cpu = pxa270_init(verdex_ram, cpu_model ?: "pxa270-c0");
+    cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     if (!dinfo) {
index 37e543aa255ffe4adf628b54d46aed2bdb5300af..a65192d4a247aaa264b641fae5575d2c6ed2d506 100644 (file)
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -234,7 +234,7 @@ static const VMStateDescription vmstate_gus = {
 
 static int gus_initfn (ISADevice *dev)
 {
-    GUSState *s = DO_UPCAST(GUSState, dev, dev);
+    GUSState *s = DO_UPCAST (GUSState, dev, dev);
     struct audsettings as;
 
     AUD_register_card ("gus", &s->card);
@@ -264,24 +264,23 @@ static int gus_initfn (ISADevice *dev)
 
     register_ioport_write (s->port, 1, 1, gus_writeb, s);
     register_ioport_write (s->port, 1, 2, gus_writew, s);
-    isa_init_ioport_range(dev, s->port, 2);
+    isa_init_ioport_range (dev, s->port, 2);
 
     register_ioport_read ((s->port + 0x100) & 0xf00, 1, 1, gus_readb, s);
     register_ioport_read ((s->port + 0x100) & 0xf00, 1, 2, gus_readw, s);
-    isa_init_ioport_range(dev, (s->port + 0x100) & 0xf00, 2);
+    isa_init_ioport_range (dev, (s->port + 0x100) & 0xf00, 2);
 
     register_ioport_write (s->port + 6, 10, 1, gus_writeb, s);
     register_ioport_write (s->port + 6, 10, 2, gus_writew, s);
     register_ioport_read (s->port + 6, 10, 1, gus_readb, s);
     register_ioport_read (s->port + 6, 10, 2, gus_readw, s);
-    isa_init_ioport_range(dev, s->port + 6, 10);
-
+    isa_init_ioport_range (dev, s->port + 6, 10);
 
     register_ioport_write (s->port + 0x100, 8, 1, gus_writeb, s);
     register_ioport_write (s->port + 0x100, 8, 2, gus_writew, s);
     register_ioport_read (s->port + 0x100, 8, 1, gus_readb, s);
     register_ioport_read (s->port + 0x100, 8, 2, gus_readw, s);
-    isa_init_ioport_range(dev, s->port + 0x100, 8);
+    isa_init_ioport_range (dev, s->port + 0x100, 8);
 
     DMA_register_channel (s->emu.gusdma, GUS_read_DMA, s);
     s->emu.himemaddr = s->himem;
index 51996ab793818c9c27e4ab5dd706031da2c89017..16f48d12e10368863a540e5e91c5bcdf5c401b1c 100644 (file)
@@ -126,7 +126,7 @@ static uint64_t pic_read(void *opaque, target_phys_addr_t addr,
 static const MemoryRegionOps heathrow_pic_ops = {
     .read = pic_read,
     .write = pic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static void heathrow_pic_set_irq(void *opaque, int num, int level)
index 75a03a74b956e0e124fcad9942b486b077b29f7b..e077ec07cc812b455fa943036d6e7c4d278cf69b 100644 (file)
@@ -697,7 +697,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len)
         lsi_reselect(s, p);
         return 0;
     } else {
-        DPRINTF("Queueing IO tag=0x%x\n", tag);
+        DPRINTF("Queueing IO tag=0x%x\n", p->tag);
         p->pending = len;
         return 1;
     }
index 336f31e64e9281353e66fc55c6c763651141d3e2..3ed6649204ceca51b94f6f6fce5c888acefe00ab 100644 (file)
@@ -110,7 +110,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
         cpu_model = "pxa270-c5";
 
     /* Setup CPU & memory */
-    cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model);
+    cpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
     memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM);
     memory_region_set_readonly(rom, true);
     memory_region_add_subregion(address_space_mem, 0, rom);
index 6104732f7d12f486873b814ddb3bd9600df0bcdd..5c5ed275b36d884b634c02764024303bbfaf8e9a 100644 (file)
@@ -53,6 +53,7 @@ enum {
 
 struct MilkymistAC97State {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
 
     QEMUSoundCard card;
     SWVoiceIn *voice_in;
@@ -82,7 +83,8 @@ static void update_voices(MilkymistAC97State *s)
     }
 }
 
-static uint32_t ac97_read(void *opaque, target_phys_addr_t addr)
+static uint64_t ac97_read(void *opaque, target_phys_addr_t addr,
+                          unsigned size)
 {
     MilkymistAC97State *s = opaque;
     uint32_t r = 0;
@@ -113,7 +115,8 @@ static uint32_t ac97_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void ac97_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                       unsigned size)
 {
     MilkymistAC97State *s = opaque;
 
@@ -159,16 +162,14 @@ static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t value)
 
 }
 
-static CPUReadMemoryFunc * const ac97_read_fn[] = {
-    NULL,
-    NULL,
-    &ac97_read,
-};
-
-static CPUWriteMemoryFunc * const ac97_write_fn[] = {
-    NULL,
-    NULL,
-    &ac97_write,
+static const MemoryRegionOps ac97_mmio_ops = {
+    .read = ac97_read,
+    .write = ac97_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void ac97_in_cb(void *opaque, int avail_b)
@@ -280,7 +281,6 @@ static int ac97_post_load(void *opaque, int version_id)
 static int milkymist_ac97_init(SysBusDevice *dev)
 {
     MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev);
-    int ac97_regs;
 
     struct audsettings as;
     sysbus_init_irq(dev, &s->crrequest_irq);
@@ -300,9 +300,9 @@ static int milkymist_ac97_init(SysBusDevice *dev)
     s->voice_out = AUD_open_out(&s->card, s->voice_out,
             "mm_ac97.out", s, ac97_out_cb, &as);
 
-    ac97_regs = cpu_register_io_memory(ac97_read_fn, ac97_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, ac97_regs);
+    memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s,
+            "milkymist-ac97", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     return 0;
 }
index c0962fb528334f7055b9d8e9ce2536e18380dc58..17c840ff08486049acd36799c99338e02187bbd1 100644 (file)
@@ -42,12 +42,14 @@ enum {
 
 struct MilkymistHpdmcState {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
 
     uint32_t regs[R_MAX];
 };
 typedef struct MilkymistHpdmcState MilkymistHpdmcState;
 
-static uint32_t hpdmc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t hpdmc_read(void *opaque, target_phys_addr_t addr,
+                           unsigned size)
 {
     MilkymistHpdmcState *s = opaque;
     uint32_t r = 0;
@@ -72,7 +74,8 @@ static uint32_t hpdmc_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void hpdmc_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void hpdmc_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                        unsigned size)
 {
     MilkymistHpdmcState *s = opaque;
 
@@ -96,16 +99,14 @@ static void hpdmc_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const hpdmc_read_fn[] = {
-    NULL,
-    NULL,
-    &hpdmc_read,
-};
-
-static CPUWriteMemoryFunc * const hpdmc_write_fn[] = {
-    NULL,
-    NULL,
-    &hpdmc_write,
+static const MemoryRegionOps hpdmc_mmio_ops = {
+    .read = hpdmc_read,
+    .write = hpdmc_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void milkymist_hpdmc_reset(DeviceState *d)
@@ -125,11 +126,10 @@ static void milkymist_hpdmc_reset(DeviceState *d)
 static int milkymist_hpdmc_init(SysBusDevice *dev)
 {
     MilkymistHpdmcState *s = FROM_SYSBUS(typeof(*s), dev);
-    int hpdmc_regs;
 
-    hpdmc_regs = cpu_register_io_memory(hpdmc_read_fn, hpdmc_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, hpdmc_regs);
+    memory_region_init_io(&s->regs_region, &hpdmc_mmio_ops, s,
+            "milkymist-hpdmc", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     return 0;
 }
index 20de68ecce6bb3158ae364b5b0ca2262e8442783..9f358a7d691c4865ea8f4b71592c8e28a84d945c 100644 (file)
@@ -5,15 +5,14 @@
 #include "qdev-addr.h"
 
 static inline DeviceState *milkymist_uart_create(target_phys_addr_t base,
-        qemu_irq rx_irq, qemu_irq tx_irq)
+        qemu_irq irq)
 {
     DeviceState *dev;
 
     dev = qdev_create(NULL, "milkymist-uart");
     qdev_init_nofail(dev);
     sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
 
     return dev;
 }
index 22dc377d79a7f7fb45d3e1a8e85dc7efa3c3ff96..fb6e558755428f62b15804f6358a7edf13b09d29 100644 (file)
@@ -60,6 +60,7 @@ enum {
 
 struct MilkymistMemcardState {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
     SDState *card;
 
     int command_write_ptr;
@@ -116,7 +117,8 @@ static void memcard_sd_command(MilkymistMemcardState *s)
     }
 }
 
-static uint32_t memcard_read(void *opaque, target_phys_addr_t addr)
+static uint64_t memcard_read(void *opaque, target_phys_addr_t addr,
+                             unsigned size)
 {
     MilkymistMemcardState *s = opaque;
     uint32_t r = 0;
@@ -164,7 +166,8 @@ static uint32_t memcard_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void memcard_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void memcard_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                          unsigned size)
 {
     MilkymistMemcardState *s = opaque;
 
@@ -216,16 +219,14 @@ static void memcard_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const memcard_read_fn[] = {
-    NULL,
-    NULL,
-    &memcard_read,
-};
-
-static CPUWriteMemoryFunc * const memcard_write_fn[] = {
-    NULL,
-    NULL,
-    &memcard_write,
+static const MemoryRegionOps memcard_mmio_ops = {
+    .read = memcard_read,
+    .write = memcard_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void milkymist_memcard_reset(DeviceState *d)
@@ -247,15 +248,14 @@ static int milkymist_memcard_init(SysBusDevice *dev)
 {
     MilkymistMemcardState *s = FROM_SYSBUS(typeof(*s), dev);
     DriveInfo *dinfo;
-    int memcard_regs;
 
     dinfo = drive_get_next(IF_SD);
     s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0);
     s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0;
 
-    memcard_regs = cpu_register_io_memory(memcard_read_fn, memcard_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, memcard_regs);
+    memory_region_init_io(&s->regs_region, &memcard_mmio_ops, s,
+            "milkymist-memcard", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     return 0;
 }
index fb48e37187ad7ba3f99b89455fafc02440600c00..85d9400c67eb89c4078e4b49857edddd6fd6c8cf 100644 (file)
@@ -464,11 +464,11 @@ static int milkymist_minimac2_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->tx_irq);
 
     memory_region_init_io(&s->regs_region, &minimac2_ops, s,
-                          "minimac2-mmio", R_MAX * 4);
+                          "milkymist-minimac2", R_MAX * 4);
     sysbus_init_mmio_region(dev, &s->regs_region);
 
     /* register buffers memory */
-    memory_region_init_ram(&s->buffers, NULL, "milkymist_minimac2.buffers",
+    memory_region_init_ram(&s->buffers, NULL, "milkymist-minimac2.buffers",
                            buffers_size);
     s->rx0_buf = memory_region_get_ram_ptr(&s->buffers);
     s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
index 306d1ce2878ab0f23563a78a2542b4169ef2a209..672f6e43eb687879f6b97be2ef5e65f3dab9a904 100644 (file)
@@ -118,6 +118,7 @@ static const char *opcode_to_str[] = {
 
 struct MilkymistPFPUState {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
     CharDriverState *chr;
     qemu_irq irq;
 
@@ -379,7 +380,8 @@ static inline int get_microcode_address(MilkymistPFPUState *s, uint32_t addr)
     return (512 * s->regs[R_CODEPAGE]) + addr - MICROCODE_BEGIN;
 }
 
-static uint32_t pfpu_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pfpu_read(void *opaque, target_phys_addr_t addr,
+                          unsigned size)
 {
     MilkymistPFPUState *s = opaque;
     uint32_t r = 0;
@@ -418,8 +420,8 @@ static uint32_t pfpu_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void
-pfpu_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void pfpu_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                       unsigned size)
 {
     MilkymistPFPUState *s = opaque;
 
@@ -459,16 +461,14 @@ pfpu_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const pfpu_read_fn[] = {
-    NULL,
-    NULL,
-    &pfpu_read,
-};
-
-static CPUWriteMemoryFunc * const pfpu_write_fn[] = {
-    NULL,
-    NULL,
-    &pfpu_write,
+static const MemoryRegionOps pfpu_mmio_ops = {
+    .read = pfpu_read,
+    .write = pfpu_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void milkymist_pfpu_reset(DeviceState *d)
@@ -494,13 +494,12 @@ static void milkymist_pfpu_reset(DeviceState *d)
 static int milkymist_pfpu_init(SysBusDevice *dev)
 {
     MilkymistPFPUState *s = FROM_SYSBUS(typeof(*s), dev);
-    int pfpu_regs;
 
     sysbus_init_irq(dev, &s->irq);
 
-    pfpu_regs = cpu_register_io_memory(pfpu_read_fn, pfpu_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, MICROCODE_END * 4, pfpu_regs);
+    memory_region_init_io(&s->regs_region, &pfpu_mmio_ops, s,
+            "milkymist-pfpu", MICROCODE_END * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     return 0;
 }
index ef4d9ee2ce06759825a09548f1866afc62f10e5e..ec5f3343d444f8b96852f0085e962d6e4e0ec7d3 100644 (file)
@@ -267,10 +267,10 @@ static int milkymist_softusb_init(SysBusDevice *dev)
     sysbus_init_mmio_region(dev, &s->regs_region);
 
     /* register pmem and dmem */
-    memory_region_init_ram(&s->pmem, NULL, "milkymist_softusb.pmem",
+    memory_region_init_ram(&s->pmem, NULL, "milkymist-softusb.pmem",
                            s->pmem_size);
     sysbus_add_memory(dev, s->pmem_base, &s->pmem);
-    memory_region_init_ram(&s->dmem, NULL, "milkymist_softusb.dmem",
+    memory_region_init_ram(&s->dmem, NULL, "milkymist-softusb.dmem",
                            s->dmem_size);
     sysbus_add_memory(dev, s->dmem_base, &s->dmem);
 
index 7b2d544ac35d67e46e50f090d5c4606279cb9e95..5783f083b196d94ffc8b23feea146bb67ecad3da 100644 (file)
@@ -59,6 +59,7 @@ enum {
 
 struct MilkymistSysctlState {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
 
     QEMUBH *bh0;
     QEMUBH *bh1;
@@ -88,7 +89,8 @@ static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value)
     }
 }
 
-static uint32_t sysctl_read(void *opaque, target_phys_addr_t addr)
+static uint64_t sysctl_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     MilkymistSysctlState *s = opaque;
     uint32_t r = 0;
@@ -129,7 +131,8 @@ static uint32_t sysctl_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void sysctl_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                         unsigned size)
 {
     MilkymistSysctlState *s = opaque;
 
@@ -195,16 +198,14 @@ static void sysctl_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const sysctl_read_fn[] = {
-    NULL,
-    NULL,
-    &sysctl_read,
-};
-
-static CPUWriteMemoryFunc * const sysctl_write_fn[] = {
-    NULL,
-    NULL,
-    &sysctl_write,
+static const MemoryRegionOps sysctl_mmio_ops = {
+    .read = sysctl_read,
+    .write = sysctl_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void timer0_hit(void *opaque)
@@ -258,7 +259,6 @@ static void milkymist_sysctl_reset(DeviceState *d)
 static int milkymist_sysctl_init(SysBusDevice *dev)
 {
     MilkymistSysctlState *s = FROM_SYSBUS(typeof(*s), dev);
-    int sysctl_regs;
 
     sysbus_init_irq(dev, &s->gpio_irq);
     sysbus_init_irq(dev, &s->timer0_irq);
@@ -271,9 +271,9 @@ static int milkymist_sysctl_init(SysBusDevice *dev)
     ptimer_set_freq(s->ptimer0, s->freq_hz);
     ptimer_set_freq(s->ptimer1, s->freq_hz);
 
-    sysctl_regs = cpu_register_io_memory(sysctl_read_fn, sysctl_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, sysctl_regs);
+    memory_region_init_io(&s->regs_region, &sysctl_mmio_ops, s,
+            "milkymist-sysctl", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     return 0;
 }
index 953d42f16baff83de021279cd56b5b989eaa6b03..aad0ed06d42b1d6c5f55e0db7ba2f8910dc82d86 100644 (file)
@@ -77,6 +77,7 @@ struct vertex {
 
 struct MilkymistTMU2State {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
     CharDriverState *chr;
     qemu_irq irq;
 
@@ -309,7 +310,8 @@ static void tmu2_start(MilkymistTMU2State *s)
     qemu_irq_pulse(s->irq);
 }
 
-static uint32_t tmu2_read(void *opaque, target_phys_addr_t addr)
+static uint64_t tmu2_read(void *opaque, target_phys_addr_t addr,
+                          unsigned size)
 {
     MilkymistTMU2State *s = opaque;
     uint32_t r = 0;
@@ -370,7 +372,8 @@ static void tmu2_check_registers(MilkymistTMU2State *s)
     }
 }
 
-static void tmu2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void tmu2_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                       unsigned size)
 {
     MilkymistTMU2State *s = opaque;
 
@@ -414,16 +417,14 @@ static void tmu2_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     tmu2_check_registers(s);
 }
 
-static CPUReadMemoryFunc * const tmu2_read_fn[] = {
-    NULL,
-    NULL,
-    &tmu2_read,
-};
-
-static CPUWriteMemoryFunc * const tmu2_write_fn[] = {
-    NULL,
-    NULL,
-    &tmu2_write,
+static const MemoryRegionOps tmu2_mmio_ops = {
+    .read = tmu2_read,
+    .write = tmu2_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void milkymist_tmu2_reset(DeviceState *d)
@@ -439,7 +440,6 @@ static void milkymist_tmu2_reset(DeviceState *d)
 static int milkymist_tmu2_init(SysBusDevice *dev)
 {
     MilkymistTMU2State *s = FROM_SYSBUS(typeof(*s), dev);
-    int tmu2_regs;
 
     if (tmu2_glx_init(s)) {
         return 1;
@@ -447,9 +447,9 @@ static int milkymist_tmu2_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
 
-    tmu2_regs = cpu_register_io_memory(tmu2_read_fn, tmu2_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, tmu2_regs);
+    memory_region_init_io(&s->regs_region, &tmu2_mmio_ops, s,
+            "milkymist-tmu2", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     return 0;
 }
index e8e309de7cd0a0cea368df6488fd083649b47a0b..5404ca998cf9811f77559eb7f0f278d9eed9da2e 100644 (file)
 enum {
     R_RXTX = 0,
     R_DIV,
+    R_STAT,
+    R_CTRL,
+    R_DBG,
     R_MAX
 };
 
+enum {
+    STAT_THRE   = (1<<0),
+    STAT_RX_EVT = (1<<1),
+    STAT_TX_EVT = (1<<2),
+};
+
+enum {
+    CTRL_RX_IRQ_EN = (1<<0),
+    CTRL_TX_IRQ_EN = (1<<1),
+    CTRL_THRU_EN   = (1<<2),
+};
+
+enum {
+    DBG_BREAK_EN = (1<<0),
+};
+
 struct MilkymistUartState {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
     CharDriverState *chr;
-    qemu_irq rx_irq;
-    qemu_irq tx_irq;
+    qemu_irq irq;
 
     uint32_t regs[R_MAX];
 };
 typedef struct MilkymistUartState MilkymistUartState;
 
-static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
+static void uart_update_irq(MilkymistUartState *s)
+{
+    int rx_event = s->regs[R_STAT] & STAT_RX_EVT;
+    int tx_event = s->regs[R_STAT] & STAT_TX_EVT;
+    int rx_irq_en = s->regs[R_CTRL] & CTRL_RX_IRQ_EN;
+    int tx_irq_en = s->regs[R_CTRL] & CTRL_TX_IRQ_EN;
+
+    if ((rx_irq_en && rx_event) || (tx_irq_en && tx_event)) {
+        trace_milkymist_uart_raise_irq();
+        qemu_irq_raise(s->irq);
+    } else {
+        trace_milkymist_uart_lower_irq();
+        qemu_irq_lower(s->irq);
+    }
+}
+
+static uint64_t uart_read(void *opaque, target_phys_addr_t addr,
+                          unsigned size)
 {
     MilkymistUartState *s = opaque;
     uint32_t r = 0;
@@ -51,7 +87,12 @@ static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
     addr >>= 2;
     switch (addr) {
     case R_RXTX:
+        r = s->regs[addr];
+        break;
     case R_DIV:
+    case R_STAT:
+    case R_CTRL:
+    case R_DBG:
         r = s->regs[addr];
         break;
 
@@ -66,7 +107,8 @@ static uint32_t uart_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void uart_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                       unsigned size)
 {
     MilkymistUartState *s = opaque;
     unsigned char ch = value;
@@ -79,44 +121,55 @@ static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value)
         if (s->chr) {
             qemu_chr_fe_write(s->chr, &ch, 1);
         }
-        trace_milkymist_uart_pulse_irq_tx();
-        qemu_irq_pulse(s->tx_irq);
+        s->regs[R_STAT] |= STAT_TX_EVT;
         break;
     case R_DIV:
+    case R_CTRL:
+    case R_DBG:
         s->regs[addr] = value;
         break;
 
+    case R_STAT:
+        /* write one to clear bits */
+        s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT));
+        break;
+
     default:
         error_report("milkymist_uart: write access to unknown register 0x"
                 TARGET_FMT_plx, addr << 2);
         break;
     }
-}
 
-static CPUReadMemoryFunc * const uart_read_fn[] = {
-    NULL,
-    NULL,
-    &uart_read,
-};
+    uart_update_irq(s);
+}
 
-static CPUWriteMemoryFunc * const uart_write_fn[] = {
-    NULL,
-    NULL,
-    &uart_write,
+static const MemoryRegionOps uart_mmio_ops = {
+    .read = uart_read,
+    .write = uart_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void uart_rx(void *opaque, const uint8_t *buf, int size)
 {
     MilkymistUartState *s = opaque;
 
+    assert(!(s->regs[R_STAT] & STAT_RX_EVT));
+
+    s->regs[R_STAT] |= STAT_RX_EVT;
     s->regs[R_RXTX] = *buf;
-    trace_milkymist_uart_pulse_irq_rx();
-    qemu_irq_pulse(s->rx_irq);
+
+    uart_update_irq(s);
 }
 
 static int uart_can_rx(void *opaque)
 {
-    return 1;
+    MilkymistUartState *s = opaque;
+
+    return !(s->regs[R_STAT] & STAT_RX_EVT);
 }
 
 static void uart_event(void *opaque, int event)
@@ -131,19 +184,20 @@ static void milkymist_uart_reset(DeviceState *d)
     for (i = 0; i < R_MAX; i++) {
         s->regs[i] = 0;
     }
+
+    /* THRE is always set */
+    s->regs[R_STAT] = STAT_THRE;
 }
 
 static int milkymist_uart_init(SysBusDevice *dev)
 {
     MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
-    int uart_regs;
 
-    sysbus_init_irq(dev, &s->rx_irq);
-    sysbus_init_irq(dev, &s->tx_irq);
+    sysbus_init_irq(dev, &s->irq);
 
-    uart_regs = cpu_register_io_memory(uart_read_fn, uart_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
+    memory_region_init_io(&s->regs_region, &uart_mmio_ops, s,
+            "milkymist-uart", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
index 2e55e42e34124e86cc49fcf8ad4149d84c352f88..be81abdb08d816145d291c4a4e56acdc59f1f88d 100644 (file)
@@ -64,6 +64,7 @@ enum {
 
 struct MilkymistVgafbState {
     SysBusDevice busdev;
+    MemoryRegion regs_region;
     DisplayState *ds;
 
     int invalidate;
@@ -153,7 +154,8 @@ static void vgafb_resize(MilkymistVgafbState *s)
     s->invalidate = 1;
 }
 
-static uint32_t vgafb_read(void *opaque, target_phys_addr_t addr)
+static uint64_t vgafb_read(void *opaque, target_phys_addr_t addr,
+                           unsigned size)
 {
     MilkymistVgafbState *s = opaque;
     uint32_t r = 0;
@@ -189,8 +191,8 @@ static uint32_t vgafb_read(void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-static void
-vgafb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void vgafb_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                        unsigned size)
 {
     MilkymistVgafbState *s = opaque;
 
@@ -238,16 +240,14 @@ vgafb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const vgafb_read_fn[] = {
-   NULL,
-   NULL,
-   &vgafb_read
-};
-
-static CPUWriteMemoryFunc * const vgafb_write_fn[] = {
-   NULL,
-   NULL,
-   &vgafb_write
+static const MemoryRegionOps vgafb_mmio_ops = {
+    .read = vgafb_read,
+    .write = vgafb_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void milkymist_vgafb_reset(DeviceState *d)
@@ -269,11 +269,10 @@ static void milkymist_vgafb_reset(DeviceState *d)
 static int milkymist_vgafb_init(SysBusDevice *dev)
 {
     MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev);
-    int vgafb_regs;
 
-    vgafb_regs = cpu_register_io_memory(vgafb_read_fn, vgafb_write_fn, s,
-            DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, R_MAX * 4, vgafb_regs);
+    memory_region_init_io(&s->regs_region, &vgafb_mmio_ops, s,
+            "milkymist-vgafb", R_MAX * 4);
+    sysbus_init_mmio_region(dev, &s->regs_region);
 
     s->ds = graphic_console_init(vgafb_update_display,
                                  vgafb_invalidate_display,
index bca0a58d8cb3e5ff98189929c2bf7a83337a8186..b7a8c1c25603f6846c6f44c3952ec288f2e805e0 100644 (file)
@@ -146,17 +146,17 @@ milkymist_init(ram_addr_t ram_size_not_used,
         exit(1);
     }
 
-    milkymist_uart_create(0x60000000, irq[0], irq[1]);
-    milkymist_sysctl_create(0x60001000, irq[2], irq[3], irq[4],
+    milkymist_uart_create(0x60000000, irq[0]);
+    milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3],
             80000000, 0x10014d31, 0x0000041f, 0x00000001);
     milkymist_hpdmc_create(0x60002000);
     milkymist_vgafb_create(0x60003000, 0x40000000, 0x0fffffff);
     milkymist_memcard_create(0x60004000);
-    milkymist_ac97_create(0x60005000, irq[5], irq[6], irq[7], irq[8]);
-    milkymist_pfpu_create(0x60006000, irq[9]);
-    milkymist_tmu2_create(0x60007000, irq[10]);
-    milkymist_minimac2_create(0x60008000, 0x30000000, irq[11], irq[12]);
-    milkymist_softusb_create(0x6000f000, irq[17],
+    milkymist_ac97_create(0x60005000, irq[4], irq[5], irq[6], irq[7]);
+    milkymist_pfpu_create(0x60006000, irq[8]);
+    milkymist_tmu2_create(0x60007000, irq[9]);
+    milkymist_minimac2_create(0x60008000, 0x30000000, irq[10], irq[11]);
+    milkymist_softusb_create(0x6000f000, irq[15],
             0x20000000, 0x1000, 0x20020000, 0x2000);
 
     /* make sure juart isn't the first chardev */
index ea07d32eadb5ba4cabb3c9b00fb94c6c5809773b..14beea2d64b5b760b0797f45baeeb6e27af8bd5c 100644 (file)
@@ -264,18 +264,12 @@ static void mips_jazz_init(MemoryRegion *address_space,
 
     /* Serial ports */
     if (serial_hds[0]) {
-#ifdef TARGET_WORDS_BIGENDIAN
-        serial_mm_init(0x80006000, 0, rc4030[8], 8000000/16, serial_hds[0], 1, 1);
-#else
-        serial_mm_init(0x80006000, 0, rc4030[8], 8000000/16, serial_hds[0], 1, 0);
-#endif
+        serial_mm_init(address_space, 0x80006000, 0, rc4030[8], 8000000/16,
+                       serial_hds[0], DEVICE_NATIVE_ENDIAN);
     }
     if (serial_hds[1]) {
-#ifdef TARGET_WORDS_BIGENDIAN
-        serial_mm_init(0x80007000, 0, rc4030[9], 8000000/16, serial_hds[1], 1, 1);
-#else
-        serial_mm_init(0x80007000, 0, rc4030[9], 8000000/16, serial_hds[1], 1, 0);
-#endif
+        serial_mm_init(address_space, 0x80007000, 0, rc4030[9], 8000000/16,
+                       serial_hds[1], DEVICE_NATIVE_ENDIAN);
     }
 
     /* Parallel port */
index 1ec1228b87dcc8353a15798f76dd99b3ca6f30ab..bb497495695810e14aed15cd9dbb068e480085d8 100644 (file)
@@ -446,11 +446,8 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
 
     s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1, 1);
-#else
-    s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1, 0);
-#endif
+    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
+                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
 
     malta_fpga_reset(s);
     qemu_register_reset(malta_fpga_reset, s);
index 9b1f38062bc4b127d4c9c97c1d9599354a9fa757..20553b525bd3435379f061e798b8e3deb1032d7a 100644 (file)
@@ -1486,22 +1486,12 @@ static void musicpal_init(ram_addr_t ram_size,
                           pic[MP_TIMER4_IRQ], NULL);
 
     if (serial_hds[0]) {
-#ifdef TARGET_WORDS_BIGENDIAN
-        serial_mm_init(MP_UART1_BASE, 2, pic[MP_UART1_IRQ], 1825000,
-                       serial_hds[0], 1, 1);
-#else
-        serial_mm_init(MP_UART1_BASE, 2, pic[MP_UART1_IRQ], 1825000,
-                       serial_hds[0], 1, 0);
-#endif
+        serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ],
+                       1825000, serial_hds[0], DEVICE_NATIVE_ENDIAN);
     }
     if (serial_hds[1]) {
-#ifdef TARGET_WORDS_BIGENDIAN
-        serial_mm_init(MP_UART2_BASE, 2, pic[MP_UART2_IRQ], 1825000,
-                       serial_hds[1], 1, 1);
-#else
-        serial_mm_init(MP_UART2_BASE, 2, pic[MP_UART2_IRQ], 1825000,
-                       serial_hds[1], 1, 0);
-#endif
+        serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ],
+                       1825000, serial_hds[1], DEVICE_NATIVE_ENDIAN);
     }
 
     /* Register flash */
index 191a0c2ccd9720feef176adcfff14214db192d23..19f8e6eec9be07bdefd5c948a5d3571ee3a96664 100644 (file)
@@ -22,6 +22,7 @@
 #include "omap.h"
 /* We use pc-style serial ports.  */
 #include "pc.h"
+#include "exec-memory.h"
 
 /* UARTs */
 struct omap_uart_s {
@@ -60,15 +61,10 @@ struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
     s->base = base;
     s->fclk = fclk;
     s->irq = irq;
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->serial = serial_mm_init(base, 2, irq, omap_clk_getrate(fclk)/16,
-                               chr ?: qemu_chr_new(label, "null", NULL), 1,
-                               1);
-#else
-    s->serial = serial_mm_init(base, 2, irq, omap_clk_getrate(fclk)/16,
-                               chr ?: qemu_chr_new(label, "null", NULL), 1,
-                               0);
-#endif
+    s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
+                               omap_clk_getrate(fclk)/16,
+                               chr ?: qemu_chr_new(label, "null", NULL),
+                               DEVICE_NATIVE_ENDIAN);
     return s;
 }
 
@@ -182,15 +178,8 @@ struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
 void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr)
 {
     /* TODO: Should reuse or destroy current s->serial */
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->serial = serial_mm_init(s->base, 2, s->irq,
+    s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
                                omap_clk_getrate(s->fclk) / 16,
-                               chr ?: qemu_chr_new("null", "null", NULL), 1,
-                               1);
-#else
-    s->serial = serial_mm_init(s->base, 2, s->irq,
-                               omap_clk_getrate(s->fclk) / 16,
-                               chr ?: qemu_chr_new("null", "null", NULL), 1,
-                               0);
-#endif
+                               chr ?: qemu_chr_new("null", "null", NULL),
+                               DEVICE_NATIVE_ENDIAN);
 }
index 26c96e20f9af6cbdd3fd0c08e4eb09b2df90455a..22fc275b626d940398c22ede174437af37b3438c 100644 (file)
@@ -2,6 +2,7 @@
  * OpenPIC emulation
  *
  * Copyright (c) 2004 Jocelyn Mayer
+ *               2011 Alexander Graf
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #define MAX_MBX     4
 #define MAX_TMR     4
 #define VECTOR_BITS 8
-#define MAX_IPI     0
+#define MAX_IPI     4
 
 #define VID (0x00000000)
 
 #elif defined(USE_MPCxxx)
 
-#define MAX_CPU     2
+#define MAX_CPU    15
 #define MAX_IRQ   128
 #define MAX_DBL     0
 #define MAX_MBX     0
@@ -127,14 +128,14 @@ enum {
 #define MPIC_MSI_REG_START        0x11C00
 #define MPIC_MSI_REG_SIZE         0x100
 #define MPIC_CPU_REG_START        0x20000
-#define MPIC_CPU_REG_SIZE         0x100
+#define MPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
 
 enum mpic_ide_bits {
-    IDR_EP     = 0,
-    IDR_CI0     = 1,
-    IDR_CI1     = 2,
-    IDR_P1     = 30,
-    IDR_P0     = 31,
+    IDR_EP     = 31,
+    IDR_CI0     = 30,
+    IDR_CI1     = 29,
+    IDR_P1     = 1,
+    IDR_P0     = 0,
 };
 
 #else
@@ -161,6 +162,16 @@ static inline int test_bit (uint32_t *field, int bit)
     return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
 }
 
+static int get_current_cpu(void)
+{
+  return cpu_single_env->cpu_index;
+}
+
+static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
+                                          int idx);
+static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
+                                       uint32_t val, int idx);
+
 enum {
     IRQ_EXTERNAL = 0x01,
     IRQ_INTERNAL = 0x02,
@@ -206,6 +217,10 @@ typedef struct IRQ_dst_t {
 typedef struct openpic_t {
     PCIDevice pci_dev;
     MemoryRegion mem;
+
+    /* Sub-regions */
+    MemoryRegion sub_io_mem[7];
+
     /* Global registers */
     uint32_t frep; /* Feature reporting register */
     uint32_t glbc; /* Global configuration register  */
@@ -461,46 +476,35 @@ static void openpic_reset (void *opaque)
     opp->glbc = 0x00000000;
 }
 
-static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
+static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
 {
-    uint32_t retval;
-
-    switch (reg) {
-    case IRQ_IPVP:
-        retval = opp->src[n_IRQ].ipvp;
-        break;
-    case IRQ_IDE:
-        retval = opp->src[n_IRQ].ide;
-        break;
-    }
+    return opp->src[n_IRQ].ide;
+}
 
-    return retval;
+static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
+{
+    return opp->src[n_IRQ].ipvp;
 }
 
-static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
-                                 uint32_t reg, uint32_t val)
+static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
 {
     uint32_t tmp;
 
-    switch (reg) {
-    case IRQ_IPVP:
-        /* NOTE: not fully accurate for special IRQs, but simple and
-           sufficient */
-        /* ACTIVITY bit is read-only */
-        opp->src[n_IRQ].ipvp =
-            (opp->src[n_IRQ].ipvp & 0x40000000) |
-            (val & 0x800F00FF);
-        openpic_update_irq(opp, n_IRQ);
-        DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
-                n_IRQ, val, opp->src[n_IRQ].ipvp);
-        break;
-    case IRQ_IDE:
-        tmp = val & 0xC0000000;
-        tmp |= val & ((1 << MAX_CPU) - 1);
-        opp->src[n_IRQ].ide = tmp;
-        DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
-        break;
-    }
+    tmp = val & 0xC0000000;
+    tmp |= val & ((1ULL << MAX_CPU) - 1);
+    opp->src[n_IRQ].ide = tmp;
+    DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
+}
+
+static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
+{
+    /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
+    /* ACTIVITY bit is read-only */
+    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
+                         | (val & 0x800F00FF);
+    openpic_update_irq(opp, n_IRQ);
+    DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
+            opp->src[n_IRQ].ipvp);
 }
 
 #if 0 // Code provision for Intel model
@@ -512,10 +516,10 @@ static uint32_t read_doorbell_register (openpic_t *opp,
 
     switch (offset) {
     case DBL_IPVP_OFFSET:
-        retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
+        retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
         break;
     case DBL_IDE_OFFSET:
-        retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
+        retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
         break;
     case DBL_DMR_OFFSET:
         retval = opp->doorbells[n_dbl].dmr;
@@ -530,10 +534,10 @@ static void write_doorbell_register (penpic_t *opp, int n_dbl,
 {
     switch (offset) {
     case DBL_IVPR_OFFSET:
-        write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
+        write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
         break;
     case DBL_IDE_OFFSET:
-        write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
+        write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
         break;
     case DBL_DMR_OFFSET:
         opp->doorbells[n_dbl].dmr = value;
@@ -553,10 +557,10 @@ static uint32_t read_mailbox_register (openpic_t *opp,
         retval = opp->mailboxes[n_mbx].mbr;
         break;
     case MBX_IVPR_OFFSET:
-        retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
+        retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
         break;
     case MBX_DMR_OFFSET:
-        retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
+        retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
         break;
     }
 
@@ -571,10 +575,10 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx,
         opp->mailboxes[n_mbx].mbr = value;
         break;
     case MBX_IVPR_OFFSET:
-        write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
+        write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
         break;
     case MBX_DMR_OFFSET:
-        write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
+        write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
         break;
     }
 }
@@ -590,18 +594,27 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v
     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
         return;
-    addr &= 0xFF;
     switch (addr) {
-    case 0x00: /* FREP */
+    case 0x40:
+    case 0x50:
+    case 0x60:
+    case 0x70:
+    case 0x80:
+    case 0x90:
+    case 0xA0:
+    case 0xB0:
+        openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
+        break;
+    case 0x1000: /* FREP */
         break;
-    case 0x20: /* GLBC */
+    case 0x1020: /* GLBC */
         if (val & 0x80000000 && opp->reset)
             opp->reset(opp);
         opp->glbc = val & ~0x80000000;
         break;
-    case 0x80: /* VENI */
+    case 0x1080: /* VENI */
         break;
-    case 0x90: /* PINT */
+    case 0x1090: /* PINT */
         for (idx = 0; idx < opp->nb_cpus; idx++) {
             if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
                 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
@@ -615,22 +628,20 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v
         }
         opp->pint = val;
         break;
-#if MAX_IPI > 0
-    case 0xA0: /* IPI_IPVP */
-    case 0xB0:
-    case 0xC0:
-    case 0xD0:
+    case 0x10A0: /* IPI_IPVP */
+    case 0x10B0:
+    case 0x10C0:
+    case 0x10D0:
         {
             int idx;
-            idx = (addr - 0xA0) >> 4;
-            write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val);
+            idx = (addr - 0x10A0) >> 4;
+            write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
         }
         break;
-#endif
-    case 0xE0: /* SPVE */
+    case 0x10E0: /* SPVE */
         opp->spve = val & 0x000000FF;
         break;
-    case 0xF0: /* TIFR */
+    case 0x10F0: /* TIFR */
         opp->tifr = val;
         break;
     default:
@@ -647,36 +658,43 @@ static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
     retval = 0xFFFFFFFF;
     if (addr & 0xF)
         return retval;
-    addr &= 0xFF;
     switch (addr) {
-    case 0x00: /* FREP */
+    case 0x1000: /* FREP */
         retval = opp->frep;
         break;
-    case 0x20: /* GLBC */
+    case 0x1020: /* GLBC */
         retval = opp->glbc;
         break;
-    case 0x80: /* VENI */
+    case 0x1080: /* VENI */
         retval = opp->veni;
         break;
-    case 0x90: /* PINT */
+    case 0x1090: /* PINT */
         retval = 0x00000000;
         break;
-#if MAX_IPI > 0
-    case 0xA0: /* IPI_IPVP */
+    case 0x40:
+    case 0x50:
+    case 0x60:
+    case 0x70:
+    case 0x80:
+    case 0x90:
+    case 0xA0:
     case 0xB0:
-    case 0xC0:
-    case 0xD0:
+        retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
+        break;
+    case 0x10A0: /* IPI_IPVP */
+    case 0x10B0:
+    case 0x10C0:
+    case 0x10D0:
         {
             int idx;
-            idx = (addr - 0xA0) >> 4;
-            retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP);
+            idx = (addr - 0x10A0) >> 4;
+            retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
         }
         break;
-#endif
-    case 0xE0: /* SPVE */
+    case 0x10E0: /* SPVE */
         retval = opp->spve;
         break;
-    case 0xF0: /* TIFR */
+    case 0x10F0: /* TIFR */
         retval = opp->tifr;
         break;
     default:
@@ -710,10 +728,10 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
         opp->timers[idx].tibc = val;
         break;
     case 0x20: /* TIVP */
-        write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP, val);
+        write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
         break;
     case 0x30: /* TIDE */
-        write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, val);
+        write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
         break;
     }
 }
@@ -740,10 +758,10 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
         retval = opp->timers[idx].tibc;
         break;
     case 0x20: /* TIPV */
-        retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP);
+        retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
         break;
     case 0x30: /* TIDE */
-        retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE);
+        retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
         break;
     }
     DPRINTF("%s: => %08x\n", __func__, retval);
@@ -763,10 +781,10 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
     idx = addr >> 5;
     if (addr & 0x10) {
         /* EXDE / IFEDE / IEEDE */
-        write_IRQreg(opp, idx, IRQ_IDE, val);
+        write_IRQreg_ide(opp, idx, val);
     } else {
         /* EXVP / IFEVP / IEEVP */
-        write_IRQreg(opp, idx, IRQ_IPVP, val);
+        write_IRQreg_ipvp(opp, idx, val);
     }
 }
 
@@ -784,38 +802,40 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr)
     idx = addr >> 5;
     if (addr & 0x10) {
         /* EXDE / IFEDE / IEEDE */
-        retval = read_IRQreg(opp, idx, IRQ_IDE);
+        retval = read_IRQreg_ide(opp, idx);
     } else {
         /* EXVP / IFEVP / IEEVP */
-        retval = read_IRQreg(opp, idx, IRQ_IPVP);
+        retval = read_IRQreg_ipvp(opp, idx);
     }
     DPRINTF("%s: => %08x\n", __func__, retval);
 
     return retval;
 }
 
-static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t val)
+static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
+                                       uint32_t val, int idx)
 {
     openpic_t *opp = opaque;
     IRQ_src_t *src;
     IRQ_dst_t *dst;
-    int idx, s_IRQ, n_IRQ;
+    int s_IRQ, n_IRQ;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
+            addr, val);
     if (addr & 0xF)
         return;
-    addr &= 0x1FFF0;
-    idx = addr / 0x1000;
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
 #if MAX_IPI > 0
-    case 0x40: /* PIPD */
+    case 0x40: /* IPIDR */
     case 0x50:
     case 0x60:
     case 0x70:
         idx = (addr - 0x40) >> 4;
-        write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
+        /* we use IDE as mask which CPUs to deliver the IPI to still. */
+        write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
+                         opp->src[opp->irq_ipi0 + idx].ide | val);
         openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
         openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
         break;
@@ -852,20 +872,24 @@ static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t v
     }
 }
 
-static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
+static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
+}
+
+static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
+                                          int idx)
 {
     openpic_t *opp = opaque;
     IRQ_src_t *src;
     IRQ_dst_t *dst;
     uint32_t retval;
-    int idx, n_IRQ;
+    int n_IRQ;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
     retval = 0xFFFFFFFF;
     if (addr & 0xF)
         return retval;
-    addr &= 0x1FFF0;
-    idx = addr / 0x1000;
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
@@ -905,18 +929,22 @@ static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
                 reset_bit(&src->ipvp, IPVP_ACTIVITY);
                 src->pending = 0;
             }
+
+            if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
+                src->ide &= ~(1 << idx);
+                if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
+                    /* trigger on CPUs that didn't know about it yet */
+                    openpic_set_irq(opp, n_IRQ, 1);
+                    openpic_set_irq(opp, n_IRQ, 0);
+                    /* if all CPUs knew about it, set active bit again */
+                    set_bit(&src->ipvp, IPVP_ACTIVITY);
+                }
+            }
         }
         break;
     case 0xB0: /* PEOI */
         retval = 0;
         break;
-#if MAX_IPI > 0
-    case 0x40: /* IDE */
-    case 0x50:
-        idx = (addr - 0x40) >> 4;
-        retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE);
-        break;
-#endif
     default:
         break;
     }
@@ -925,6 +953,11 @@ static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
     return retval;
 }
 
+static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr)
+{
+    return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
+}
+
 static void openpic_buggy_write (void *opaque,
                                  target_phys_addr_t addr, uint32_t val)
 {
@@ -1243,7 +1276,7 @@ static void mpic_reset (void *opaque)
 
     mpp->glbc = 0x80000000;
     /* Initialise controller registers */
-    mpp->frep = 0x004f0002;
+    mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
     mpp->veni = VENI;
     mpp->pint = 0x00000000;
     mpp->spve = 0x0000FFFF;
@@ -1252,6 +1285,10 @@ static void mpic_reset (void *opaque)
         mpp->src[i].ipvp = 0x80800000;
         mpp->src[i].ide  = 0x00000001;
     }
+    /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
+    for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
+        mpp->src[i].ide = 0;
+    }
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
         mpp->dst[i].pctp      = 0x0000000F;
@@ -1292,13 +1329,13 @@ static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t va
         mpp->timers[idx].tibc = val;
         break;
     case 0x20: /* GTIVPR */
-        write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP, val);
+        write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
         break;
     case 0x30: /* GTIDR & TFRR */
         if ((addr & 0xF0) == 0xF0)
             mpp->dst[cpu].tfrr = val;
         else
-            write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE, val);
+            write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
         break;
     }
 }
@@ -1324,13 +1361,13 @@ static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
         retval = mpp->timers[idx].tibc;
         break;
     case 0x20: /* TIPV */
-        retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP);
+        retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
         break;
     case 0x30: /* TIDR */
         if ((addr &0xF0) == 0XF0)
             retval = mpp->dst[cpu].tfrr;
         else
-            retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE);
+            retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
         break;
     }
     DPRINTF("%s: => %08x\n", __func__, retval);
@@ -1353,10 +1390,10 @@ static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            write_IRQreg(mpp, idx, IRQ_IDE, val);
+            write_IRQreg_ide(mpp, idx, val);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            write_IRQreg(mpp, idx, IRQ_IPVP, val);
+            write_IRQreg_ipvp(mpp, idx, val);
         }
     }
 }
@@ -1377,10 +1414,10 @@ static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            retval = read_IRQreg(mpp, idx, IRQ_IDE);
+            retval = read_IRQreg_ide(mpp, idx);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            retval = read_IRQreg(mpp, idx, IRQ_IPVP);
+            retval = read_IRQreg_ipvp(mpp, idx);
         }
         DPRINTF("%s: => %08x\n", __func__, retval);
     }
@@ -1403,10 +1440,10 @@ static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            write_IRQreg(mpp, idx, IRQ_IDE, val);
+            write_IRQreg_ide(mpp, idx, val);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            write_IRQreg(mpp, idx, IRQ_IPVP, val);
+            write_IRQreg_ipvp(mpp, idx, val);
         }
     }
 }
@@ -1427,10 +1464,10 @@ static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            retval = read_IRQreg(mpp, idx, IRQ_IDE);
+            retval = read_IRQreg_ide(mpp, idx);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            retval = read_IRQreg(mpp, idx, IRQ_IPVP);
+            retval = read_IRQreg_ipvp(mpp, idx);
         }
         DPRINTF("%s: => %08x\n", __func__, retval);
     }
@@ -1453,10 +1490,10 @@ static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            write_IRQreg(mpp, idx, IRQ_IDE, val);
+            write_IRQreg_ide(mpp, idx, val);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            write_IRQreg(mpp, idx, IRQ_IPVP, val);
+            write_IRQreg_ipvp(mpp, idx, val);
         }
     }
 }
@@ -1477,10 +1514,10 @@ static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            retval = read_IRQreg(mpp, idx, IRQ_IDE);
+            retval = read_IRQreg_ide(mpp, idx);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            retval = read_IRQreg(mpp, idx, IRQ_IPVP);
+            retval = read_IRQreg_ipvp(mpp, idx);
         }
         DPRINTF("%s: => %08x\n", __func__, retval);
     }
@@ -1503,10 +1540,10 @@ static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            write_IRQreg(mpp, idx, IRQ_IDE, val);
+            write_IRQreg_ide(mpp, idx, val);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            write_IRQreg(mpp, idx, IRQ_IPVP, val);
+            write_IRQreg_ipvp(mpp, idx, val);
         }
     }
 }
@@ -1526,10 +1563,10 @@ static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
         idx += (addr & 0xFFF0) >> 5;
         if (addr & 0x10) {
             /* EXDE / IFEDE / IEEDE */
-            retval = read_IRQreg(mpp, idx, IRQ_IDE);
+            retval = read_IRQreg_ide(mpp, idx);
         } else {
             /* EXVP / IFEVP / IEEVP */
-            retval = read_IRQreg(mpp, idx, IRQ_IPVP);
+            retval = read_IRQreg_ipvp(mpp, idx);
         }
         DPRINTF("%s: => %08x\n", __func__, retval);
     }
@@ -1537,125 +1574,136 @@ static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
     return retval;
 }
 
-static CPUWriteMemoryFunc * const mpic_glb_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &openpic_gbl_write,
+static const MemoryRegionOps mpic_glb_ops = {
+    .old_mmio = {
+        .write = { openpic_buggy_write,
+                   openpic_buggy_write,
+                   openpic_gbl_write,
+        },
+        .read  = { openpic_buggy_read,
+                   openpic_buggy_read,
+                   openpic_gbl_read,
+        },
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const mpic_glb_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &openpic_gbl_read,
+static const MemoryRegionOps mpic_tmr_ops = {
+    .old_mmio = {
+        .write = { openpic_buggy_write,
+                   openpic_buggy_write,
+                   mpic_timer_write,
+        },
+        .read  = { openpic_buggy_read,
+                   openpic_buggy_read,
+                   mpic_timer_read,
+        },
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mpic_tmr_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &mpic_timer_write,
+static const MemoryRegionOps mpic_cpu_ops = {
+    .old_mmio = {
+        .write = { openpic_buggy_write,
+                   openpic_buggy_write,
+                   openpic_cpu_write,
+        },
+        .read  = { openpic_buggy_read,
+                   openpic_buggy_read,
+                   openpic_cpu_read,
+        },
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const mpic_tmr_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &mpic_timer_read,
+static const MemoryRegionOps mpic_ext_ops = {
+    .old_mmio = {
+        .write = { openpic_buggy_write,
+                   openpic_buggy_write,
+                   mpic_src_ext_write,
+        },
+        .read  = { openpic_buggy_read,
+                   openpic_buggy_read,
+                   mpic_src_ext_read,
+        },
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mpic_cpu_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &openpic_cpu_write,
+static const MemoryRegionOps mpic_int_ops = {
+    .old_mmio = {
+        .write = { openpic_buggy_write,
+                   openpic_buggy_write,
+                   mpic_src_int_write,
+        },
+        .read  = { openpic_buggy_read,
+                   openpic_buggy_read,
+                   mpic_src_int_read,
+        },
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const mpic_cpu_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &openpic_cpu_read,
+static const MemoryRegionOps mpic_msg_ops = {
+    .old_mmio = {
+        .write = { openpic_buggy_write,
+                   openpic_buggy_write,
+                   mpic_src_msg_write,
+        },
+        .read  = { openpic_buggy_read,
+                   openpic_buggy_read,
+                   mpic_src_msg_read,
+        },
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const mpic_ext_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &mpic_src_ext_write,
+static const MemoryRegionOps mpic_msi_ops = {
+    .old_mmio = {
+        .write = { openpic_buggy_write,
+                   openpic_buggy_write,
+                   mpic_src_msi_write,
+        },
+        .read  = { openpic_buggy_read,
+                   openpic_buggy_read,
+                   mpic_src_msi_read,
+        },
+    },
+    .endianness = DEVICE_BIG_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const mpic_ext_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &mpic_src_ext_read,
-};
-
-static CPUWriteMemoryFunc * const mpic_int_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &mpic_src_int_write,
-};
-
-static CPUReadMemoryFunc * const mpic_int_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &mpic_src_int_read,
-};
-
-static CPUWriteMemoryFunc * const mpic_msg_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &mpic_src_msg_write,
-};
-
-static CPUReadMemoryFunc * const mpic_msg_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &mpic_src_msg_read,
-};
-static CPUWriteMemoryFunc * const mpic_msi_write[] = {
-    &openpic_buggy_write,
-    &openpic_buggy_write,
-    &mpic_src_msi_write,
-};
-
-static CPUReadMemoryFunc * const mpic_msi_read[] = {
-    &openpic_buggy_read,
-    &openpic_buggy_read,
-    &mpic_src_msi_read,
-};
-
-qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
-                        qemu_irq **irqs, qemu_irq irq_out)
+qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
+                     int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
 {
-    openpic_t *mpp;
-    int i;
+    openpic_t    *mpp;
+    int           i;
     struct {
-        CPUReadMemoryFunc * const *read;
-        CPUWriteMemoryFunc * const *write;
-        target_phys_addr_t start_addr;
-        ram_addr_t size;
+        const char             *name;
+        MemoryRegionOps const  *ops;
+        target_phys_addr_t      start_addr;
+        ram_addr_t              size;
     } const list[] = {
-        {mpic_glb_read, mpic_glb_write, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
-        {mpic_tmr_read, mpic_tmr_write, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
-        {mpic_ext_read, mpic_ext_write, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
-        {mpic_int_read, mpic_int_write, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
-        {mpic_msg_read, mpic_msg_write, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
-        {mpic_msi_read, mpic_msi_write, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
-        {mpic_cpu_read, mpic_cpu_write, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
+        {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
+        {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
+        {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
+        {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
+        {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
+        {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
+        {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
     };
 
-    /* XXX: for now, only one CPU is supported */
-    if (nb_cpus != 1)
-        return NULL;
-
     mpp = g_malloc0(sizeof(openpic_t));
 
+    memory_region_init(&mpp->mem, "mpic", 0x40000);
+    memory_region_add_subregion(address_space, base, &mpp->mem);
+
     for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
-        int mem_index;
 
-        mem_index = cpu_register_io_memory(list[i].read, list[i].write, mpp,
-                                           DEVICE_BIG_ENDIAN);
-        if (mem_index < 0) {
-            goto free;
-        }
-        cpu_register_physical_memory(base + list[i].start_addr,
-                                     list[i].size, mem_index);
+        memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
+                              list[i].name, list[i].size);
+
+        memory_region_add_subregion(&mpp->mem, list[i].start_addr,
+                                    &mpp->sub_io_mem[i]);
     }
 
     mpp->nb_cpus = nb_cpus;
@@ -1674,8 +1722,4 @@ qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
     qemu_register_reset(mpic_reset, mpp);
 
     return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
-
-free:
-    g_free(mpp);
-    return NULL;
 }
index 75de3616ada1ec1e5c2e367d8faddc046975a802..715f0847bf435e5812859d3a18a37f16ead36d83 100644 (file)
@@ -13,6 +13,6 @@ enum {
 
 qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
                         qemu_irq **irqs, qemu_irq irq_out);
-qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
-                        qemu_irq **irqs, qemu_irq irq_out);
+qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
+                     int nb_cpus, qemu_irq **irqs, qemu_irq irq_out);
 #endif /* __OPENPIC_H__ */
diff --git a/hw/pc.h b/hw/pc.h
index 7e6ddbab827c751fbc6b88c1848a24d1c603ab4d..f3e21b62252ae9eeb496e3adcb10428af6d3de6f 100644 (file)
--- a/hw/pc.h
+++ b/hw/pc.h
 
 SerialState *serial_init(int base, qemu_irq irq, int baudbase,
                          CharDriverState *chr);
-SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
-                             qemu_irq irq, int baudbase,
-                             CharDriverState *chr, int ioregister,
-                             int be);
+SerialState *serial_mm_init(MemoryRegion *address_space,
+                            target_phys_addr_t base, int it_shift,
+                            qemu_irq irq, int baudbase,
+                            CharDriverState *chr, enum device_endian);
 static inline bool serial_isa_init(int index, CharDriverState *chr)
 {
     ISADevice *dev;
index 38db521b379f5c24ae866336b61df97e6ef7882e..2a0f7fd031bc567f853a0c49ae237ba0958e34b6 100644 (file)
@@ -38,6 +38,7 @@
 #include "elf.h"
 #include "blockdev.h"
 #include "pc.h"
+#include "exec-memory.h"
 
 #include "microblaze_pic_cpu.h"
 #include "xilinx_axidma.h"
@@ -141,6 +142,7 @@ petalogix_ml605_init(ram_addr_t ram_size,
                           const char *kernel_cmdline,
                           const char *initrd_filename, const char *cpu_model)
 {
+    MemoryRegion *address_space_mem = get_system_memory();
     DeviceState *dev;
     CPUState *env;
     int kernel_size;
@@ -184,8 +186,8 @@ petalogix_ml605_init(ram_addr_t ram_size,
         irq[i] = qdev_get_gpio_in(dev, i);
     }
 
-    serial_mm_init(UART16550_BASEADDR + 0x1000, 2, irq[5], 115200,
-                   serial_hds[0], 1, 0);
+    serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2,
+                   irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN);
 
     /* 2 timers at irq 2 @ 100 Mhz.  */
     xilinx_timer_create(TIMER_BASEADDR, irq[2], 2, 100 * 1000000);
index 887074822b7c4bb03e77f7bcfeecb140ee1afac2..25b59dddaa0716401f2d7bea0b0237dd2083202f 100644 (file)
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -50,7 +50,7 @@
 static void cpu_ppc_tb_stop (CPUState *env);
 static void cpu_ppc_tb_start (CPUState *env);
 
-static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
+void ppc_set_irq(CPUState *env, int n_IRQ, int level)
 {
     unsigned int old_pending = env->pending_interrupts;
 
@@ -423,25 +423,8 @@ void ppce500_irq_init (CPUState *env)
 }
 /*****************************************************************************/
 /* PowerPC time base and decrementer emulation */
-struct ppc_tb_t {
-    /* Time base management */
-    int64_t  tb_offset;    /* Compensation                    */
-    int64_t  atb_offset;   /* Compensation                    */
-    uint32_t tb_freq;      /* TB frequency                    */
-    /* Decrementer management */
-    uint64_t decr_next;    /* Tick for next decr interrupt    */
-    uint32_t decr_freq;    /* decrementer frequency           */
-    struct QEMUTimer *decr_timer;
-    /* Hypervisor decrementer management */
-    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
-    struct QEMUTimer *hdecr_timer;
-    uint64_t purr_load;
-    uint64_t purr_start;
-    void *opaque;
-};
 
-static inline uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk,
-                                      int64_t tb_offset)
+uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
 {
     /* TB time in tb periods */
     return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
@@ -611,10 +594,13 @@ static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next)
     int64_t diff;
 
     diff = next - qemu_get_clock_ns(vm_clock);
-    if (diff >= 0)
+    if (diff >= 0) {
         decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
-    else
+    } else if (tb_env->flags & PPC_TIMER_BOOKE) {
+        decr = 0;
+    }  else {
         decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
+    }
     LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
 
     return decr;
@@ -678,18 +664,24 @@ static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
                 decr, value);
     now = qemu_get_clock_ns(vm_clock);
     next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
-    if (is_excp)
+    if (is_excp) {
         next += *nextp - now;
-    if (next == now)
+    }
+    if (next == now) {
         next++;
+    }
     *nextp = next;
     /* Adjust timer */
     qemu_mod_timer(timer, next);
-    /* If we set a negative value and the decrementer was positive,
-     * raise an exception.
+
+    /* If we set a negative value and the decrementer was positive, raise an
+     * exception.
      */
-    if ((value & 0x80000000) && !(decr & 0x80000000))
+    if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
+        && (value & 0x80000000)
+        && !(decr & 0x80000000)) {
         (*raise_excp)(env);
+    }
 }
 
 static inline void _cpu_ppc_store_decr(CPUState *env, uint32_t decr,
@@ -763,6 +755,7 @@ clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
 
     tb_env = g_malloc0(sizeof(ppc_tb_t));
     env->tb_env = tb_env;
+    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
     /* Create new timer */
     tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env);
     if (0) {
@@ -806,11 +799,11 @@ uint32_t cpu_ppc601_load_rtcl (CPUState *env)
 }
 
 /*****************************************************************************/
-/* Embedded PowerPC timers */
+/* PowerPC 40x timers */
 
 /* PIT, FIT & WDT */
-typedef struct ppcemb_timer_t ppcemb_timer_t;
-struct ppcemb_timer_t {
+typedef struct ppc40x_timer_t ppc40x_timer_t;
+struct ppc40x_timer_t {
     uint64_t pit_reload;  /* PIT auto-reload value        */
     uint64_t fit_next;    /* Tick for next FIT interrupt  */
     struct QEMUTimer *fit_timer;
@@ -826,12 +819,12 @@ static void cpu_4xx_fit_cb (void *opaque)
 {
     CPUState *env;
     ppc_tb_t *tb_env;
-    ppcemb_timer_t *ppcemb_timer;
+    ppc40x_timer_t *ppc40x_timer;
     uint64_t now, next;
 
     env = opaque;
     tb_env = env->tb_env;
-    ppcemb_timer = tb_env->opaque;
+    ppc40x_timer = tb_env->opaque;
     now = qemu_get_clock_ns(vm_clock);
     switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
     case 0:
@@ -853,7 +846,7 @@ static void cpu_4xx_fit_cb (void *opaque)
     next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
     if (next == now)
         next++;
-    qemu_mod_timer(ppcemb_timer->fit_timer, next);
+    qemu_mod_timer(ppc40x_timer->fit_timer, next);
     env->spr[SPR_40x_TSR] |= 1 << 26;
     if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
         ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
@@ -865,11 +858,11 @@ static void cpu_4xx_fit_cb (void *opaque)
 /* Programmable interval timer */
 static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
 {
-    ppcemb_timer_t *ppcemb_timer;
+    ppc40x_timer_t *ppc40x_timer;
     uint64_t now, next;
 
-    ppcemb_timer = tb_env->opaque;
-    if (ppcemb_timer->pit_reload <= 1 ||
+    ppc40x_timer = tb_env->opaque;
+    if (ppc40x_timer->pit_reload <= 1 ||
         !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
         (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
         /* Stop PIT */
@@ -877,9 +870,9 @@ static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
         qemu_del_timer(tb_env->decr_timer);
     } else {
         LOG_TB("%s: start PIT %016" PRIx64 "\n",
-                    __func__, ppcemb_timer->pit_reload);
+                    __func__, ppc40x_timer->pit_reload);
         now = qemu_get_clock_ns(vm_clock);
-        next = now + muldiv64(ppcemb_timer->pit_reload,
+        next = now + muldiv64(ppc40x_timer->pit_reload,
                               get_ticks_per_sec(), tb_env->decr_freq);
         if (is_excp)
             next += tb_env->decr_next - now;
@@ -894,21 +887,21 @@ static void cpu_4xx_pit_cb (void *opaque)
 {
     CPUState *env;
     ppc_tb_t *tb_env;
-    ppcemb_timer_t *ppcemb_timer;
+    ppc40x_timer_t *ppc40x_timer;
 
     env = opaque;
     tb_env = env->tb_env;
-    ppcemb_timer = tb_env->opaque;
+    ppc40x_timer = tb_env->opaque;
     env->spr[SPR_40x_TSR] |= 1 << 27;
     if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
-        ppc_set_irq(env, ppcemb_timer->decr_excp, 1);
+        ppc_set_irq(env, ppc40x_timer->decr_excp, 1);
     start_stop_pit(env, tb_env, 1);
     LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
            "%016" PRIx64 "\n", __func__,
            (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
            (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
            env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
-           ppcemb_timer->pit_reload);
+           ppc40x_timer->pit_reload);
 }
 
 /* Watchdog timer */
@@ -916,12 +909,12 @@ static void cpu_4xx_wdt_cb (void *opaque)
 {
     CPUState *env;
     ppc_tb_t *tb_env;
-    ppcemb_timer_t *ppcemb_timer;
+    ppc40x_timer_t *ppc40x_timer;
     uint64_t now, next;
 
     env = opaque;
     tb_env = env->tb_env;
-    ppcemb_timer = tb_env->opaque;
+    ppc40x_timer = tb_env->opaque;
     now = qemu_get_clock_ns(vm_clock);
     switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
     case 0:
@@ -948,13 +941,13 @@ static void cpu_4xx_wdt_cb (void *opaque)
     switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
     case 0x0:
     case 0x1:
-        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
-        ppcemb_timer->wdt_next = next;
+        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+        ppc40x_timer->wdt_next = next;
         env->spr[SPR_40x_TSR] |= 1 << 31;
         break;
     case 0x2:
-        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
-        ppcemb_timer->wdt_next = next;
+        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+        ppc40x_timer->wdt_next = next;
         env->spr[SPR_40x_TSR] |= 1 << 30;
         if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
             ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
@@ -982,12 +975,12 @@ static void cpu_4xx_wdt_cb (void *opaque)
 void store_40x_pit (CPUState *env, target_ulong val)
 {
     ppc_tb_t *tb_env;
-    ppcemb_timer_t *ppcemb_timer;
+    ppc40x_timer_t *ppc40x_timer;
 
     tb_env = env->tb_env;
-    ppcemb_timer = tb_env->opaque;
+    ppc40x_timer = tb_env->opaque;
     LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
-    ppcemb_timer->pit_reload = val;
+    ppc40x_timer->pit_reload = val;
     start_stop_pit(env, tb_env, 0);
 }
 
@@ -996,31 +989,7 @@ target_ulong load_40x_pit (CPUState *env)
     return cpu_ppc_load_decr(env);
 }
 
-void store_booke_tsr (CPUState *env, target_ulong val)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    ppcemb_timer_t *ppcemb_timer;
-
-    ppcemb_timer = tb_env->opaque;
-
-    LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
-    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
-    if (val & 0x80000000)
-        ppc_set_irq(env, ppcemb_timer->decr_excp, 0);
-}
-
-void store_booke_tcr (CPUState *env, target_ulong val)
-{
-    ppc_tb_t *tb_env;
-
-    tb_env = env->tb_env;
-    LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
-    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
-    start_stop_pit(env, tb_env, 1);
-    cpu_4xx_wdt_cb(env);
-}
-
-static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
+static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
 {
     CPUState *env = opaque;
     ppc_tb_t *tb_env = env->tb_env;
@@ -1032,30 +1001,31 @@ static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
     /* XXX: we should also update all timers */
 }
 
-clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq,
+clk_setup_cb ppc_40x_timers_init (CPUState *env, uint32_t freq,
                                   unsigned int decr_excp)
 {
     ppc_tb_t *tb_env;
-    ppcemb_timer_t *ppcemb_timer;
+    ppc40x_timer_t *ppc40x_timer;
 
     tb_env = g_malloc0(sizeof(ppc_tb_t));
     env->tb_env = tb_env;
-    ppcemb_timer = g_malloc0(sizeof(ppcemb_timer_t));
+    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
+    ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
     tb_env->tb_freq = freq;
     tb_env->decr_freq = freq;
-    tb_env->opaque = ppcemb_timer;
+    tb_env->opaque = ppc40x_timer;
     LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
-    if (ppcemb_timer != NULL) {
+    if (ppc40x_timer != NULL) {
         /* We use decr timer for PIT */
         tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
-        ppcemb_timer->fit_timer =
+        ppc40x_timer->fit_timer =
             qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
-        ppcemb_timer->wdt_timer =
+        ppc40x_timer->wdt_timer =
             qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
-        ppcemb_timer->decr_excp = decr_excp;
+        ppc40x_timer->decr_excp = decr_excp;
     }
 
-    return &ppc_emb_set_tb_clk;
+    return &ppc_40x_set_tb_clk;
 }
 
 /*****************************************************************************/
index 3ccf13479b31eed9e889d1fa2e8def1bd830a80d..9f911704af1447cc7ae9e8a84de96d202495c2c3 100644 (file)
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -1,3 +1,5 @@
+void ppc_set_irq (CPUState *env, int n_IRQ, int level);
+
 /* PowerPC hardware exceptions management helpers */
 typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
 typedef struct clk_setup_t clk_setup_t;
@@ -11,6 +13,36 @@ static inline void clk_setup (clk_setup_t *clk, uint32_t freq)
         (*clk->cb)(clk->opaque, freq);
 }
 
+struct ppc_tb_t {
+    /* Time base management */
+    int64_t  tb_offset;    /* Compensation                    */
+    int64_t  atb_offset;   /* Compensation                    */
+    uint32_t tb_freq;      /* TB frequency                    */
+    /* Decrementer management */
+    uint64_t decr_next;    /* Tick for next decr interrupt    */
+    uint32_t decr_freq;    /* decrementer frequency           */
+    struct QEMUTimer *decr_timer;
+    /* Hypervisor decrementer management */
+    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
+    struct QEMUTimer *hdecr_timer;
+    uint64_t purr_load;
+    uint64_t purr_start;
+    void *opaque;
+    uint32_t flags;
+};
+
+/* PPC Timers flags */
+#define PPC_TIMER_BOOKE              (1 << 0) /* Enable Booke support */
+#define PPC_TIMER_E500               (1 << 1) /* Enable e500 support */
+#define PPC_DECR_UNDERFLOW_TRIGGERED (1 << 2) /* Decr interrupt triggered when
+                                               * the most significant bit
+                                               * changes from 0 to 1.
+                                               */
+#define PPC_DECR_ZERO_TRIGGERED      (1 << 3) /* Decr interrupt triggered when
+                                               * the decrementer reaches zero.
+                                               */
+
+uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
 clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq);
 /* Embedded PowerPC DCR management */
 typedef uint32_t (*dcr_read_cb)(void *opaque, int dcrn);
@@ -19,7 +51,7 @@ int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn),
                   int (*dcr_write_error)(int dcrn));
 int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
                       dcr_read_cb drc_read, dcr_write_cb dcr_write);
-clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq,
+clk_setup_cb ppc_40x_timers_init (CPUState *env, uint32_t freq,
                                   unsigned int decr_excp);
 
 /* Embedded PowerPC reset */
@@ -55,3 +87,6 @@ enum {
 #define FW_CFG_PPC_KVM_PID      (FW_CFG_ARCH_LOCAL + 0x07)
 
 #define PPC_SERIAL_MM_BAUDBASE 399193
+
+/* ppc_booke.c */
+void ppc_booke_timers_init(CPUState *env, uint32_t freq, uint32_t flags);
index f0e81a64957fb48e85f9a714bfc5fb412d91812d..d8fdf0930ab1e4a40facfbfdf2e9736b7920a3e8 100644 (file)
@@ -59,16 +59,18 @@ struct ppc4xx_bd_info_t {
 ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
                                 uint32_t flags);
 
-CPUState *ppc405cr_init (MemoryRegion ram_memories[4],
-                         target_phys_addr_t ram_bases[4],
-                         target_phys_addr_t ram_sizes[4],
-                         uint32_t sysclk, qemu_irq **picp,
-                         int do_init);
-CPUState *ppc405ep_init (MemoryRegion ram_memories[2],
-                         target_phys_addr_t ram_bases[2],
-                         target_phys_addr_t ram_sizes[2],
-                         uint32_t sysclk, qemu_irq **picp,
-                         int do_init);
+CPUState *ppc405cr_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[4],
+                        target_phys_addr_t ram_bases[4],
+                        target_phys_addr_t ram_sizes[4],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init);
+CPUState *ppc405ep_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[2],
+                        target_phys_addr_t ram_bases[2],
+                        target_phys_addr_t ram_sizes[2],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init);
 /* IBM STBxxx microcontrollers */
 CPUState *ppc_stb025_init (MemoryRegion ram_memories[2],
                            target_phys_addr_t ram_bases[2],
index e6c8ac67d9445bc56aa603d834cbe557c5ac501f..9136288d0893912f03556f88e98edce9a630e36d 100644 (file)
@@ -207,13 +207,14 @@ static void ref405ep_init (ram_addr_t ram_size,
 #ifdef DEBUG_BOARD_INIT
     printf("%s: register cpu\n", __func__);
 #endif
-    env = ppc405ep_init(ram_memories, ram_bases, ram_sizes, 33333333, &pic,
-                        kernel_filename == NULL ? 0 : 1);
+    env = ppc405ep_init(get_system_memory(), ram_memories, ram_bases, ram_sizes,
+                        33333333, &pic, kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
     sram_size = 512 * 1024;
     sram_offset = qemu_ram_alloc(NULL, "ef405ep.sram", sram_size);
 #ifdef DEBUG_BOARD_INIT
-    printf("%s: register SRAM at offset %08lx\n", __func__, sram_offset);
+    printf("%s: register SRAM at offset " RAM_ADDR_FMT "\n",
+           __func__, sram_offset);
 #endif
     cpu_register_physical_memory(0xFFF00000, sram_size,
                                  sram_offset | IO_MEM_RAM);
@@ -357,7 +358,7 @@ static void ref405ep_init (ram_addr_t ram_size,
 #ifdef DEBUG_BOARD_INIT
     printf("%s: Done\n", __func__);
 #endif
-    printf("bdloc %016lx\n", (unsigned long)bdloc);
+    printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
 }
 
 static QEMUMachine ref405ep_machine = {
@@ -534,8 +535,8 @@ static void taihu_405ep_init(ram_addr_t ram_size,
 #ifdef DEBUG_BOARD_INIT
     printf("%s: register cpu\n", __func__);
 #endif
-    ppc405ep_init(ram_memories, ram_bases, ram_sizes, 33333333, &pic,
-                  kernel_filename == NULL ? 0 : 1);
+    ppc405ep_init(get_system_memory(), ram_memories, ram_bases, ram_sizes,
+                  33333333, &pic, kernel_filename == NULL ? 0 : 1);
     /* allocate and load BIOS */
 #ifdef DEBUG_BOARD_INIT
     printf("%s: register BIOS\n", __func__);
index 9d5d2af5d8b88d09d86548c0202355d6ba1e6481..a6e74318829ad85a9cbdf21167b3b5c583c93e2c 100644 (file)
@@ -2107,11 +2107,12 @@ static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7],
     qemu_register_reset(ppc405cr_cpc_reset, cpc);
 }
 
-CPUState *ppc405cr_init (MemoryRegion ram_memories[4],
-                         target_phys_addr_t ram_bases[4],
-                         target_phys_addr_t ram_sizes[4],
-                         uint32_t sysclk, qemu_irq **picp,
-                         int do_init)
+CPUState *ppc405cr_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[4],
+                        target_phys_addr_t ram_bases[4],
+                        target_phys_addr_t ram_sizes[4],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init)
 {
     clk_setup_t clk_setup[PPC405CR_CLK_NB];
     qemu_irq dma_irqs[4];
@@ -2149,12 +2150,14 @@ CPUState *ppc405cr_init (MemoryRegion ram_memories[4],
     ppc405_dma_init(env, dma_irqs);
     /* Serial ports */
     if (serial_hds[0] != NULL) {
-        serial_mm_init(0xef600300, 0, pic[0], PPC_SERIAL_MM_BAUDBASE,
-                       serial_hds[0], 1, 1);
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
     }
     if (serial_hds[1] != NULL) {
-        serial_mm_init(0xef600400, 0, pic[1], PPC_SERIAL_MM_BAUDBASE,
-                       serial_hds[1], 1, 1);
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
     }
     /* IIC controller */
     ppc405_i2c_init(0xef600500, pic[2]);
@@ -2453,11 +2456,12 @@ static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8],
 #endif
 }
 
-CPUState *ppc405ep_init (MemoryRegion ram_memories[2],
-                         target_phys_addr_t ram_bases[2],
-                         target_phys_addr_t ram_sizes[2],
-                         uint32_t sysclk, qemu_irq **picp,
-                         int do_init)
+CPUState *ppc405ep_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[2],
+                        target_phys_addr_t ram_bases[2],
+                        target_phys_addr_t ram_sizes[2],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init)
 {
     clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
     qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
@@ -2504,12 +2508,14 @@ CPUState *ppc405ep_init (MemoryRegion ram_memories[2],
     ppc405_gpio_init(0xef600700);
     /* Serial ports */
     if (serial_hds[0] != NULL) {
-        serial_mm_init(0xef600300, 0, pic[0], PPC_SERIAL_MM_BAUDBASE,
-                       serial_hds[0], 1, 1);
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
     }
     if (serial_hds[1] != NULL) {
-        serial_mm_init(0xef600400, 0, pic[1], PPC_SERIAL_MM_BAUDBASE,
-                       serial_hds[1], 1, 1);
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
     }
     /* OCM */
     ppc405_ocm_init(env);
index 5885ff057c2b5ad23c05570cd0df8f193b86653e..cd8a95d52b26a2cb6f21e5a85c9b86dbad265530 100644 (file)
@@ -34,9 +34,9 @@ static const unsigned int ppc440ep_sdram_bank_sizes[] = {
     256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
 };
 
-CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
-                        const unsigned int pci_irq_nrs[4], int do_init,
-                        const char *cpu_model)
+CPUState *ppc440ep_init(MemoryRegion *address_space_mem, ram_addr_t *ram_size,
+                        PCIBus **pcip, const unsigned int pci_irq_nrs[4],
+                        int do_init, const char *cpu_model)
 {
     MemoryRegion *ram_memories
         = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
@@ -92,12 +92,14 @@ CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
     isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
 
     if (serial_hds[0] != NULL) {
-        serial_mm_init(0xef600300, 0, pic[0], PPC_SERIAL_MM_BAUDBASE,
-                       serial_hds[0], 1, 1);
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
     }
     if (serial_hds[1] != NULL) {
-        serial_mm_init(0xef600400, 0, pic[1], PPC_SERIAL_MM_BAUDBASE,
-                       serial_hds[1], 1, 1);
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
     }
 
     return env;
index a40f9176dbcf00e08536709e6258453d594ad392..9c27c36fd0b7c2aec31e39dfb362b1ea6fcc1903 100644 (file)
@@ -14,8 +14,8 @@
 
 #include "hw.h"
 
-CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
-                        const unsigned int pci_irq_nrs[4], int do_init,
-                        const char *cpu_model);
+CPUState *ppc440ep_init(MemoryRegion *address_space, ram_addr_t *ram_size,
+                        PCIBus **pcip, const unsigned int pci_irq_nrs[4],
+                        int do_init, const char *cpu_model);
 
 #endif
index 1addb6832714978f6e2c4612c6a345912a1ba0a6..b734e3a56c636e635ca6dd724fd45a6edcd6ecba 100644 (file)
@@ -23,6 +23,7 @@
 #include "device_tree.h"
 #include "loader.h"
 #include "elf.h"
+#include "exec-memory.h"
 
 #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
 
@@ -43,6 +44,8 @@ static int bamboo_load_device_tree(target_phys_addr_t addr,
     char *filename;
     int fdt_size;
     void *fdt;
+    uint32_t tb_freq = 400000000;
+    uint32_t clock_freq = 400000000;
 
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
     if (!filename) {
@@ -76,8 +79,18 @@ static int bamboo_load_device_tree(target_phys_addr_t addr,
     if (ret < 0)
         fprintf(stderr, "couldn't set /chosen/bootargs\n");
 
-    if (kvm_enabled())
-        kvmppc_fdt_update(fdt);
+    /* Copy data from the host device tree into the guest. Since the guest can
+     * directly access the timebase without host involvement, we must expose
+     * the correct frequencies. */
+    if (kvm_enabled()) {
+        tb_freq = kvmppc_get_tbfreq();
+        clock_freq = kvmppc_get_clockfreq();
+    }
+
+    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
+                              clock_freq);
+    qemu_devtree_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
+                              tb_freq);
 
     ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
     g_free(fdt);
@@ -96,6 +109,7 @@ static void bamboo_init(ram_addr_t ram_size,
                         const char *cpu_model)
 {
     unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
+    MemoryRegion *address_space_mem = get_system_memory();
     PCIBus *pcibus;
     CPUState *env;
     uint64_t elf_entry;
@@ -107,7 +121,8 @@ static void bamboo_init(ram_addr_t ram_size,
     int i;
 
     /* Setup CPU. */
-    env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1, cpu_model);
+    env = ppc440ep_init(address_space_mem, &ram_size, &pcibus,
+                        pci_irq_nrs, 1, cpu_model);
 
     if (pcibus) {
         /* Register network interfaces. */
index 349f046b2f836623697130821b978f059169bb19..d18caa419214af4d1bb6e34a4f54ba80922b1eac 100644 (file)
@@ -56,7 +56,7 @@ CPUState *ppc4xx_init (const char *cpu_model,
     cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
     cpu_clk->opaque = env;
     /* Set time-base frequency to sysclk */
-    tb_clk->cb = ppc_emb_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
+    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
     tb_clk->opaque = env;
     ppc_dcr_init(env, NULL, NULL);
     /* Register qemu callbacks */
diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c
new file mode 100644 (file)
index 0000000..8871945
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * QEMU PowerPC Booke hardware System Emulator
+ *
+ * Copyright (c) 2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "ppc.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "nvram.h"
+#include "qemu-log.h"
+#include "loader.h"
+
+
+/* Timer Control Register */
+
+#define TCR_WP_SHIFT  30        /* Watchdog Timer Period */
+#define TCR_WP_MASK   (0x3 << TCR_WP_SHIFT)
+#define TCR_WRC_SHIFT 28        /* Watchdog Timer Reset Control */
+#define TCR_WRC_MASK  (0x3 << TCR_WRC_SHIFT)
+#define TCR_WIE       (1 << 27) /* Watchdog Timer Interrupt Enable */
+#define TCR_DIE       (1 << 26) /* Decrementer Interrupt Enable */
+#define TCR_FP_SHIFT  24        /* Fixed-Interval Timer Period */
+#define TCR_FP_MASK   (0x3 << TCR_FP_SHIFT)
+#define TCR_FIE       (1 << 23) /* Fixed-Interval Timer Interrupt Enable */
+#define TCR_ARE       (1 << 22) /* Auto-Reload Enable */
+
+/* Timer Control Register (e500 specific fields) */
+
+#define TCR_E500_FPEXT_SHIFT 13 /* Fixed-Interval Timer Period Extension */
+#define TCR_E500_FPEXT_MASK  (0xf << TCR_E500_FPEXT_SHIFT)
+#define TCR_E500_WPEXT_SHIFT 17 /* Watchdog Timer Period Extension */
+#define TCR_E500_WPEXT_MASK  (0xf << TCR_E500_WPEXT_SHIFT)
+
+/* Timer Status Register  */
+
+#define TSR_FIS       (1 << 26) /* Fixed-Interval Timer Interrupt Status */
+#define TSR_DIS       (1 << 27) /* Decrementer Interrupt Status */
+#define TSR_WRS_SHIFT 28        /* Watchdog Timer Reset Status */
+#define TSR_WRS_MASK  (0x3 << TSR_WRS_SHIFT)
+#define TSR_WIS       (1 << 30) /* Watchdog Timer Interrupt Status */
+#define TSR_ENW       (1 << 31) /* Enable Next Watchdog Timer */
+
+typedef struct booke_timer_t booke_timer_t;
+struct booke_timer_t {
+
+    uint64_t fit_next;
+    struct QEMUTimer *fit_timer;
+
+    uint64_t wdt_next;
+    struct QEMUTimer *wdt_timer;
+
+    uint32_t flags;
+};
+
+static void booke_update_irq(CPUState *env)
+{
+    ppc_set_irq(env, PPC_INTERRUPT_DECR,
+                (env->spr[SPR_BOOKE_TSR] & TSR_DIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_DIE));
+
+    ppc_set_irq(env, PPC_INTERRUPT_WDT,
+                (env->spr[SPR_BOOKE_TSR] & TSR_WIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_WIE));
+
+    ppc_set_irq(env, PPC_INTERRUPT_FIT,
+                (env->spr[SPR_BOOKE_TSR] & TSR_FIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_FIE));
+}
+
+/* Return the location of the bit of time base at which the FIT will raise an
+   interrupt */
+static uint8_t booke_get_fit_target(CPUState *env, ppc_tb_t *tb_env)
+{
+    uint8_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT;
+
+    if (tb_env->flags & PPC_TIMER_E500) {
+        /* e500 Fixed-interval timer period extension */
+        uint32_t fpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_FPEXT_MASK)
+            >> TCR_E500_FPEXT_SHIFT;
+        fp = 63 - (fp | fpext << 2);
+    } else {
+        fp = env->fit_period[fp];
+    }
+
+    return fp;
+}
+
+/* Return the location of the bit of time base at which the WDT will raise an
+   interrupt */
+static uint8_t booke_get_wdt_target(CPUState *env, ppc_tb_t *tb_env)
+{
+    uint8_t wp = (env->spr[SPR_BOOKE_TCR] & TCR_WP_MASK) >> TCR_WP_SHIFT;
+
+    if (tb_env->flags & PPC_TIMER_E500) {
+        /* e500 Watchdog timer period extension */
+        uint32_t wpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_WPEXT_MASK)
+            >> TCR_E500_WPEXT_SHIFT;
+        wp = 63 - (wp | wpext << 2);
+    } else {
+        wp = env->wdt_period[wp];
+    }
+
+    return wp;
+}
+
+static void booke_update_fixed_timer(CPUState         *env,
+                                     uint8_t           target_bit,
+                                     uint64_t          *next,
+                                     struct QEMUTimer *timer)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t lapse;
+    uint64_t tb;
+    uint64_t period = 1 << (target_bit + 1);
+    uint64_t now;
+
+    now = qemu_get_clock_ns(vm_clock);
+    tb  = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
+
+    lapse = period - ((tb - (1 << target_bit)) & (period - 1));
+
+    *next = now + muldiv64(lapse, get_ticks_per_sec(), tb_env->tb_freq);
+
+    /* XXX: If expire time is now. We can't run the callback because we don't
+     * have access to it. So we just set the timer one nanosecond later.
+     */
+
+    if (*next == now) {
+        (*next)++;
+    }
+
+    qemu_mod_timer(timer, *next);
+}
+
+static void booke_decr_cb(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
+    booke_update_irq(env);
+
+    if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
+        /* Auto Reload */
+        cpu_ppc_store_decr(env, env->spr[SPR_BOOKE_DECAR]);
+    }
+}
+
+static void booke_fit_cb(void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    booke_timer = tb_env->opaque;
+    env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
+
+    booke_update_irq(env);
+
+    booke_update_fixed_timer(env,
+                             booke_get_fit_target(env, tb_env),
+                             &booke_timer->fit_next,
+                             booke_timer->fit_timer);
+}
+
+static void booke_wdt_cb(void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    booke_timer = tb_env->opaque;
+
+    /* TODO: There's lots of complicated stuff to do here */
+
+    booke_update_irq(env);
+
+    booke_update_fixed_timer(env,
+                             booke_get_wdt_target(env, tb_env),
+                             &booke_timer->wdt_next,
+                             booke_timer->wdt_timer);
+}
+
+void store_booke_tsr(CPUState *env, target_ulong val)
+{
+    env->spr[SPR_BOOKE_TSR] &= ~val;
+    booke_update_irq(env);
+}
+
+void store_booke_tcr(CPUState *env, target_ulong val)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    booke_timer_t *booke_timer = tb_env->opaque;
+
+    tb_env = env->tb_env;
+    env->spr[SPR_BOOKE_TCR] = val;
+
+    booke_update_irq(env);
+
+    booke_update_fixed_timer(env,
+                             booke_get_fit_target(env, tb_env),
+                             &booke_timer->fit_next,
+                             booke_timer->fit_timer);
+
+    booke_update_fixed_timer(env,
+                             booke_get_wdt_target(env, tb_env),
+                             &booke_timer->wdt_next,
+                             booke_timer->wdt_timer);
+
+}
+
+void ppc_booke_timers_init(CPUState *env, uint32_t freq, uint32_t flags)
+{
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    tb_env      = g_malloc0(sizeof(ppc_tb_t));
+    booke_timer = g_malloc0(sizeof(booke_timer_t));
+
+    env->tb_env = tb_env;
+    tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
+
+    tb_env->tb_freq    = freq;
+    tb_env->decr_freq  = freq;
+    tb_env->opaque     = booke_timer;
+    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, env);
+
+    booke_timer->fit_timer =
+        qemu_new_timer_ns(vm_clock, &booke_fit_cb, env);
+    booke_timer->wdt_timer =
+        qemu_new_timer_ns(vm_clock, &booke_wdt_cb, env);
+}
index 7351bb6d37867e1b16751ab49eb15fc198716306..af75e45cc2a3a0ec55e1a27f14353fd64e9af97a 100644 (file)
@@ -77,46 +77,4 @@ void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar,
 void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
 uint32_t macio_nvram_read (void *opaque, uint32_t addr);
 void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val);
-
-/* adb.c */
-
-#define MAX_ADB_DEVICES 16
-
-#define ADB_MAX_OUT_LEN 16
-
-typedef struct ADBDevice ADBDevice;
-
-/* buf = NULL means polling */
-typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out,
-                              const uint8_t *buf, int len);
-typedef int ADBDeviceReset(ADBDevice *d);
-
-struct ADBDevice {
-    struct ADBBusState *bus;
-    int devaddr;
-    int handler;
-    ADBDeviceRequest *devreq;
-    ADBDeviceReset *devreset;
-    void *opaque;
-};
-
-typedef struct ADBBusState {
-    ADBDevice devices[MAX_ADB_DEVICES];
-    int nb_devices;
-    int poll_index;
-} ADBBusState;
-
-int adb_request(ADBBusState *s, uint8_t *buf_out,
-                const uint8_t *buf, int len);
-int adb_poll(ADBBusState *s, uint8_t *buf_out);
-
-ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
-                               ADBDeviceRequest *devreq,
-                               ADBDeviceReset *devreset,
-                               void *opaque);
-void adb_kbd_init(ADBBusState *bus);
-void adb_mouse_init(ADBBusState *bus);
-
-extern ADBBusState adb_bus;
-
 #endif /* !defined(__PPC_MAC_H__) */
index b1cc3d70a731d48b910354c5bc9b94b9979fcb10..b9a50db3fa53b284587145091321e32721632ed2 100644 (file)
@@ -49,6 +49,7 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppc_mac.h"
+#include "adb.h"
 #include "mac_dbdma.h"
 #include "nvram.h"
 #include "pc.h"
index fa2c1e7768679e308137e2e756edbc0272035a96..ebcaafa641bb3cb48b8333adf3129d05116a4fbb 100644 (file)
@@ -26,6 +26,7 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppc_mac.h"
+#include "adb.h"
 #include "mac_dbdma.h"
 #include "nvram.h"
 #include "pc.h"
index 1274a3e1ebdd73bdc515acdf936c73ad0f7f8917..5bf8eab897df72753d29279af86d63e64fde54ac 100644 (file)
@@ -14,8 +14,6 @@
  * (at your option) any later version.
  */
 
-#include <dirent.h>
-
 #include "config.h"
 #include "qemu-common.h"
 #include "net.h"
@@ -32,6 +30,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "sysbus.h"
+#include "exec-memory.h"
 
 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
 #define UIMAGE_LOAD_BASE           0
@@ -51,6 +50,7 @@
 #define MPC8544_PCI_IO             0xE1000000
 #define MPC8544_PCI_IOLEN          0x10000
 #define MPC8544_UTIL_BASE          (MPC8544_CCSRBAR_BASE + 0xe0000)
+#define MPC8544_SPIN_BASE          0xEF000000
 
 struct boot_info
 {
@@ -58,30 +58,6 @@ struct boot_info
     uint32_t entry;
 };
 
-#ifdef CONFIG_FDT
-static int mpc8544_copy_soc_cell(void *fdt, const char *node, const char *prop)
-{
-    uint32_t cell;
-    int ret;
-
-    ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
-    if (ret < 0) {
-        fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
-        goto out;
-    }
-
-    ret = qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0",
-                                prop, cell);
-    if (ret < 0) {
-        fprintf(stderr, "couldn't set guest /cpus/PowerPC,8544@0/%s\n", prop);
-        goto out;
-    }
-
-out:
-    return ret;
-}
-#endif
-
 static int mpc8544_load_device_tree(CPUState *env,
                                     target_phys_addr_t addr,
                                     uint32_t ramsize,
@@ -96,6 +72,9 @@ static int mpc8544_load_device_tree(CPUState *env,
     int fdt_size;
     void *fdt;
     uint8_t hypercall[16];
+    uint32_t clock_freq = 400000000;
+    uint32_t tb_freq = 400000000;
+    int i;
 
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
     if (!filename) {
@@ -133,32 +112,9 @@ static int mpc8544_load_device_tree(CPUState *env,
         fprintf(stderr, "couldn't set /chosen/bootargs\n");
 
     if (kvm_enabled()) {
-        struct dirent *dirp;
-        DIR *dp;
-        char buf[128];
-
-        if ((dp = opendir("/proc/device-tree/cpus/")) == NULL) {
-            printf("Can't open directory /proc/device-tree/cpus/\n");
-            ret = -1;
-            goto out;
-        }
-
-        buf[0] = '\0';
-        while ((dirp = readdir(dp)) != NULL) {
-            if (strncmp(dirp->d_name, "PowerPC", 7) == 0) {
-                snprintf(buf, 128, "/cpus/%s", dirp->d_name);
-                break;
-            }
-        }
-        closedir(dp);
-        if (buf[0] == '\0') {
-            printf("Unknow host!\n");
-            ret = -1;
-            goto out;
-        }
-
-        mpc8544_copy_soc_cell(fdt, buf, "clock-frequency");
-        mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency");
+        /* Read out host's frequencies */
+        clock_freq = kvmppc_get_clockfreq();
+        tb_freq = kvmppc_get_tbfreq();
 
         /* indicate KVM hypercall interface */
         qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
@@ -166,13 +122,45 @@ static int mpc8544_load_device_tree(CPUState *env,
         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
                              hypercall, sizeof(hypercall));
-    } else {
-        const uint32_t freq = 400000000;
+    }
 
-        qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0",
-                                  "clock-frequency", freq);
-        qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,8544@0",
-                                  "timebase-frequency", freq);
+    /* We need to generate the cpu nodes in reverse order, so Linux can pick
+       the first node as boot node and be happy */
+    for (i = smp_cpus - 1; i >= 0; i--) {
+        char cpu_name[128];
+        uint64_t cpu_release_addr = cpu_to_be64(MPC8544_SPIN_BASE + (i * 0x20));
+
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            if (env->cpu_index == i) {
+                break;
+            }
+        }
+
+        if (!env) {
+            continue;
+        }
+
+        snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);
+        qemu_devtree_add_subnode(fdt, cpu_name);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
+        qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
+        qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
+                                  env->dcache_line_size);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
+                                  env->icache_line_size);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
+        qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
+        if (env->cpu_index) {
+            qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
+            qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
+            qemu_devtree_setprop(fdt, cpu_name, "cpu-release-addr",
+                                 &cpu_release_addr, sizeof(cpu_release_addr));
+        } else {
+            qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
+        }
     }
 
     ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
@@ -187,7 +175,7 @@ out:
 /* Create -kernel TLB entries for BookE, linearly spanning 256MB.  */
 static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
 {
-    return (ffs(size >> 10) - 1) >> 1;
+    return ffs(size >> 10) - 1;
 }
 
 static void mmubooke_create_initial_mapping(CPUState *env,
@@ -202,6 +190,20 @@ static void mmubooke_create_initial_mapping(CPUState *env,
     tlb->mas2 = va & TARGET_PAGE_MASK;
     tlb->mas7_3 = pa & TARGET_PAGE_MASK;
     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
+
+    env->tlb_dirty = true;
+}
+
+static void mpc8544ds_cpu_reset_sec(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_reset(env);
+
+    /* Secondary CPU starts in halted state for now. Needs to change when
+       implementing non-kernel boot. */
+    env->halted = 1;
+    env->exception_index = EXCP_HLT;
 }
 
 static void mpc8544ds_cpu_reset(void *opaque)
@@ -212,6 +214,7 @@ static void mpc8544ds_cpu_reset(void *opaque)
     cpu_reset(env);
 
     /* Set initial guest state. */
+    env->halted = 0;
     env->gpr[1] = (16<<20) - 8;
     env->gpr[3] = bi->dt_base;
     env->nip = bi->entry;
@@ -225,8 +228,9 @@ static void mpc8544ds_init(ram_addr_t ram_size,
                          const char *initrd_filename,
                          const char *cpu_model)
 {
+    MemoryRegion *address_space_mem = get_system_memory();
     PCIBus *pci_bus;
-    CPUState *env;
+    CPUState *env = NULL;
     uint64_t elf_entry;
     uint64_t elf_lowaddr;
     target_phys_addr_t entry=0;
@@ -237,27 +241,51 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     target_long initrd_size=0;
     int i=0;
     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
-    qemu_irq *irqs, *mpic;
+    qemu_irq **irqs, *mpic;
     DeviceState *dev;
-    struct boot_info *boot_info;
+    CPUState *firstenv = NULL;
 
-    /* Setup CPU */
+    /* Setup CPUs */
     if (cpu_model == NULL) {
         cpu_model = "e500v2_v30";
     }
 
-    env = cpu_ppc_init(cpu_model);
-    if (!env) {
-        fprintf(stderr, "Unable to initialize CPU!\n");
-        exit(1);
-    }
+    irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
+    irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+    for (i = 0; i < smp_cpus; i++) {
+        qemu_irq *input;
+        env = cpu_ppc_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to initialize CPU!\n");
+            exit(1);
+        }
 
-    /* XXX register timer? */
-    ppc_emb_timers_init(env, 400000000, PPC_INTERRUPT_DECR);
-    ppc_dcr_init(env, NULL, NULL);
+        if (!firstenv) {
+            firstenv = env;
+        }
+
+        irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
+        input = (qemu_irq *)env->irq_inputs;
+        irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
+        irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
+        env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
+
+        ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);
+
+        /* Register reset handler */
+        if (!i) {
+            /* Primary CPU */
+            struct boot_info *boot_info;
+            boot_info = g_malloc0(sizeof(struct boot_info));
+            qemu_register_reset(mpc8544ds_cpu_reset, env);
+            env->load_info = boot_info;
+        } else {
+            /* Secondary CPUs */
+            qemu_register_reset(mpc8544ds_cpu_reset_sec, env);
+        }
+    }
 
-    /* Register reset handler */
-    qemu_register_reset(mpc8544ds_cpu_reset, env);
+    env = firstenv;
 
     /* Fixup Memory size on a alignment boundary */
     ram_size &= ~(RAM_SIZES_ALIGN - 1);
@@ -267,22 +295,24 @@ static void mpc8544ds_init(ram_addr_t ram_size,
                                  "mpc8544ds.ram", ram_size));
 
     /* MPIC */
-    irqs = g_malloc0(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
-    irqs[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_INT];
-    irqs[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_CINT];
-    mpic = mpic_init(MPC8544_MPIC_REGS_BASE, 1, &irqs, NULL);
+    mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE,
+                     smp_cpus, irqs, NULL);
+
+    if (!mpic) {
+        cpu_abort(env, "MPIC failed to initialize\n");
+    }
 
     /* Serial */
     if (serial_hds[0]) {
-        serial_mm_init(MPC8544_SERIAL0_REGS_BASE,
+        serial_mm_init(address_space_mem, MPC8544_SERIAL0_REGS_BASE,
                        0, mpic[12+26], 399193,
-                       serial_hds[0], 1, 1);
+                       serial_hds[0], DEVICE_BIG_ENDIAN);
     }
 
     if (serial_hds[1]) {
-        serial_mm_init(MPC8544_SERIAL1_REGS_BASE,
+        serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE,
                        0, mpic[12+26], 399193,
-                       serial_hds[0], 1, 1);
+                       serial_hds[0], DEVICE_BIG_ENDIAN);
     }
 
     /* General Utility device */
@@ -306,6 +336,9 @@ static void mpc8544ds_init(ram_addr_t ram_size,
         }
     }
 
+    /* Register spinning region */
+    sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
+
     /* Load kernel. */
     if (kernel_filename) {
         kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
@@ -336,10 +369,10 @@ static void mpc8544ds_init(ram_addr_t ram_size,
         }
     }
 
-    boot_info = g_malloc0(sizeof(struct boot_info));
-
     /* If we're loading a kernel directly, we must load the device tree too. */
     if (kernel_filename) {
+        struct boot_info *boot_info;
+
 #ifndef CONFIG_FDT
         cpu_abort(env, "Compiled without FDT support - can't load kernel\n");
 #endif
@@ -350,10 +383,10 @@ static void mpc8544ds_init(ram_addr_t ram_size,
             exit(1);
         }
 
+        boot_info = env->load_info;
         boot_info->entry = entry;
         boot_info->dt_base = dt_base;
     }
-    env->load_info = boot_info;
 
     if (kvm_enabled()) {
         kvmppc_init();
@@ -364,6 +397,7 @@ static QEMUMachine mpc8544ds_machine = {
     .name = "mpc8544ds",
     .desc = "mpc8544ds",
     .init = mpc8544ds_init,
+    .max_cpus = 15,
 };
 
 static void mpc8544ds_machine_init(void)
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
new file mode 100644 (file)
index 0000000..cccd940
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * QEMU PowerPC e500v2 ePAPR spinning code
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Alexander Graf, <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * This code is not really a device, but models an interface that usually
+ * firmware takes care of. It's used when QEMU plays the role of firmware.
+ *
+ * Specification:
+ *
+ * https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.1.pdf
+ *
+ */
+
+#include "hw.h"
+#include "sysemu.h"
+#include "sysbus.h"
+#include "kvm.h"
+
+#define MAX_CPUS 32
+
+typedef struct spin_info {
+    uint64_t addr;
+    uint64_t r3;
+    uint32_t resv;
+    uint32_t pir;
+    uint64_t reserved;
+} __attribute__ ((packed)) SpinInfo;
+
+typedef struct spin_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    SpinInfo spin[MAX_CPUS];
+} SpinState;
+
+typedef struct spin_kick {
+    CPUState *env;
+    SpinInfo *spin;
+} SpinKick;
+
+static void spin_reset(void *opaque)
+{
+    SpinState *s = opaque;
+    int i;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        SpinInfo *info = &s->spin[i];
+
+        info->pir = i;
+        info->r3 = i;
+        info->addr = 1;
+    }
+}
+
+/* Create -kernel TLB entries for BookE, linearly spanning 256MB.  */
+static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
+{
+    return (ffs(size >> 10) - 1) >> 1;
+}
+
+static void mmubooke_create_initial_mapping(CPUState *env,
+                                     target_ulong va,
+                                     target_phys_addr_t pa,
+                                     target_phys_addr_t len)
+{
+    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1);
+    target_phys_addr_t size;
+
+    size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT);
+    tlb->mas1 = MAS1_VALID | size;
+    tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M;
+    tlb->mas7_3 = pa & TARGET_PAGE_MASK;
+    tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
+}
+
+static void spin_kick(void *data)
+{
+    SpinKick *kick = data;
+    CPUState *env = kick->env;
+    SpinInfo *curspin = kick->spin;
+    target_phys_addr_t map_size = 64 * 1024 * 1024;
+    target_phys_addr_t map_start;
+
+    cpu_synchronize_state(env);
+    stl_p(&curspin->pir, env->spr[SPR_PIR]);
+    env->nip = ldq_p(&curspin->addr) & (map_size - 1);
+    env->gpr[3] = ldq_p(&curspin->r3);
+    env->gpr[4] = 0;
+    env->gpr[5] = 0;
+    env->gpr[6] = 0;
+    env->gpr[7] = map_size;
+    env->gpr[8] = 0;
+    env->gpr[9] = 0;
+
+    map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
+    mmubooke_create_initial_mapping(env, 0, map_start, map_size);
+
+    env->halted = 0;
+    env->exception_index = -1;
+    qemu_cpu_kick(env);
+}
+
+static void spin_write(void *opaque, target_phys_addr_t addr, uint64_t value,
+                       unsigned len)
+{
+    SpinState *s = opaque;
+    int env_idx = addr / sizeof(SpinInfo);
+    CPUState *env;
+    SpinInfo *curspin = &s->spin[env_idx];
+    uint8_t *curspin_p = (uint8_t*)curspin;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        if (env->cpu_index == env_idx) {
+            break;
+        }
+    }
+
+    if (!env) {
+        /* Unknown CPU */
+        return;
+    }
+
+    if (!env->cpu_index) {
+        /* primary CPU doesn't spin */
+        return;
+    }
+
+    curspin_p = &curspin_p[addr % sizeof(SpinInfo)];
+    switch (len) {
+    case 1:
+        stb_p(curspin_p, value);
+        break;
+    case 2:
+        stw_p(curspin_p, value);
+        break;
+    case 4:
+        stl_p(curspin_p, value);
+        break;
+    }
+
+    if (!(ldq_p(&curspin->addr) & 1)) {
+        /* run CPU */
+        SpinKick kick = {
+            .env = env,
+            .spin = curspin,
+        };
+
+        run_on_cpu(env, spin_kick, &kick);
+    }
+}
+
+static uint64_t spin_read(void *opaque, target_phys_addr_t addr, unsigned len)
+{
+    SpinState *s = opaque;
+    uint8_t *spin_p = &((uint8_t*)s->spin)[addr];
+
+    switch (len) {
+    case 1:
+        return ldub_p(spin_p);
+    case 2:
+        return lduw_p(spin_p);
+    case 4:
+        return ldl_p(spin_p);
+    default:
+        assert(0);
+    }
+}
+
+const MemoryRegionOps spin_rw_ops = {
+    .read = spin_read,
+    .write = spin_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static int ppce500_spin_initfn(SysBusDevice *dev)
+{
+    SpinState *s;
+
+    s = FROM_SYSBUS(SpinState, sysbus_from_qdev(dev));
+
+    memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
+                          sizeof(SpinInfo) * MAX_CPUS);
+    sysbus_init_mmio_region(dev, &s->iomem);
+
+    qemu_register_reset(spin_reset, s);
+
+    return 0;
+}
+
+static SysBusDeviceInfo ppce500_spin_info = {
+    .init         = ppce500_spin_initfn,
+    .qdev.name    = "e500-spin",
+    .qdev.size    = sizeof(SpinState),
+};
+
+static void ppce500_spin_register(void)
+{
+    sysbus_register_withprop(&ppce500_spin_info);
+}
+device_init(ppce500_spin_register);
index 859fc676e48b3e91026f9bc89bb9c5dd5ac81cfd..120416554988cde6c2a8c2878825a475bbce34b3 100644 (file)
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -9,6 +9,8 @@
 #ifndef PXA_H
 # define PXA_H                 "pxa.h"
 
+#include "memory.h"
+
 /* Interrupt numbers */
 # define PXA2XX_PIC_SSP3       0
 # define PXA2XX_PIC_USBH2      2
@@ -173,7 +175,8 @@ struct PXA2xxI2SState {
 # define PA_FMT                        "0x%08lx"
 # define REG_FMT               "0x" TARGET_FMT_plx
 
-PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision);
-PXA2xxState *pxa255_init(unsigned int sdram_size);
+PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
+                         const char *revision);
+PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size);
 
 #endif /* PXA_H */
index 2aa876001e8cea954e1e92ae1a722aeaff9ec2a7..70d7c8a06d7d5f5c960f5b1d3ffe7cad3fa03b2c 100644 (file)
@@ -2059,7 +2059,8 @@ static void pxa2xx_reset(void *opaque, int line, int level)
 }
 
 /* Initialise a PXA270 integrated chip (ARM based core).  */
-PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
+PXA2xxState *pxa270_init(MemoryRegion *address_space,
+                         unsigned int sdram_size, const char *revision)
 {
     PXA2xxState *s;
     int iomemtype, i;
@@ -2113,19 +2114,16 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
 
-    for (i = 0; pxa270_serial[i].io_base; i ++)
-        if (serial_hds[i])
-#ifdef TARGET_WORDS_BIGENDIAN
-            serial_mm_init(pxa270_serial[i].io_base, 2,
-                            qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
-                            14857000 / 16, serial_hds[i], 1, 1);
-#else
-            serial_mm_init(pxa270_serial[i].io_base, 2,
-                            qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
-                            14857000 / 16, serial_hds[i], 1, 0);
-#endif
-        else
+    for (i = 0; pxa270_serial[i].io_base; i++) {
+        if (serial_hds[i]) {
+            serial_mm_init(address_space, pxa270_serial[i].io_base, 2,
+                           qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
+                           14857000 / 16, serial_hds[i],
+                           DEVICE_NATIVE_ENDIAN);
+        } else {
             break;
+        }
+    }
     if (serial_hds[i])
         s->fir = pxa2xx_fir_init(0x40800000,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
@@ -2201,7 +2199,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
 }
 
 /* Initialise a PXA255 integrated chip (ARM based core).  */
-PXA2xxState *pxa255_init(unsigned int sdram_size)
+PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
 {
     PXA2xxState *s;
     int iomemtype, i;
@@ -2248,20 +2246,16 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
 
-    for (i = 0; pxa255_serial[i].io_base; i ++)
+    for (i = 0; pxa255_serial[i].io_base; i++) {
         if (serial_hds[i]) {
-#ifdef TARGET_WORDS_BIGENDIAN
-            serial_mm_init(pxa255_serial[i].io_base, 2,
-                            qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
-                            14745600 / 16, serial_hds[i], 1, 1);
-#else
-            serial_mm_init(pxa255_serial[i].io_base, 2,
-                            qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
-                            14745600 / 16, serial_hds[i], 1, 0);
-#endif
+            serial_mm_init(address_space, pxa255_serial[i].io_base, 2,
+                           qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
+                           14745600 / 16, serial_hds[i],
+                           DEVICE_NATIVE_ENDIAN);
         } else {
             break;
         }
+    }
     if (serial_hds[i])
         s->fir = pxa2xx_fir_init(0x40800000,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
index b8b0df3bb61ac9d8dd073258b300a9581dd6564b..82377a0a105be5c825c2c530a4bd87b66b592755 100644 (file)
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -37,6 +37,7 @@
 #include "usb.h"
 #include "flash.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define FLASH_BASE 0x00000000
 #define FLASH_SIZE 0x02000000
@@ -235,6 +236,7 @@ static void r2d_init(ram_addr_t ram_size,
     qemu_irq *irq;
     DriveInfo *dinfo;
     int i;
+    MemoryRegion *address_space_mem = get_system_memory();
 
     if (!cpu_model)
         cpu_model = "SH7751R";
@@ -258,7 +260,8 @@ static void r2d_init(ram_addr_t ram_size,
     sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
                           irq[PCI_INTC], irq[PCI_INTD], NULL);
 
-    sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);
+    sm501_init(address_space_mem, 0x10000000, SM501_VRAM_SIZE,
+               irq[SM501], serial_hds[2]);
 
     /* onboard CF (True IDE mode, Master only). */
     dinfo = drive_get(IF_IDE, 0, 0);
index a76df1b1ed110372d5585d0178cabcd549cddf64..aca52e09ab8739ec6c87bdc263313c1e08472cbc 100644 (file)
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1368,20 +1368,20 @@ static int sb16_initfn (ISADevice *dev)
 
     for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) {
         register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
-        isa_init_ioport(dev, s->port + dsp_write_ports[i]);
+        isa_init_ioport (dev, s->port + dsp_write_ports[i]);
     }
 
     for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) {
         register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
-        isa_init_ioport(dev, s->port + dsp_read_ports[i]);
+        isa_init_ioport (dev, s->port + dsp_read_ports[i]);
     }
 
     register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
     register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
-    isa_init_ioport(dev, s->port + 0x4);
+    isa_init_ioport (dev, s->port + 0x4);
     register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
     register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
-    isa_init_ioport(dev, s->port + 0x5);
+    isa_init_ioport (dev, s->port + 0x5);
 
     DMA_register_channel (s->hdma, SB_read_DMA, s);
     DMA_register_channel (s->dma, SB_read_DMA, s);
index 2e6d2122d0ac56bd84f8e24ca72c40417f6e977c..d35c7a920776bbeacb13f2a90964b3d73928b0c6 100644 (file)
@@ -153,11 +153,11 @@ struct SerialState {
     int poll_msl;
 
     struct QEMUTimer *modem_status_poll;
+    MemoryRegion io;
 };
 
 typedef struct ISASerialState {
     ISADevice dev;
-    MemoryRegion io;
     uint32_t index;
     uint32_t iobase;
     uint32_t isairq;
@@ -786,8 +786,8 @@ static int serial_isa_initfn(ISADevice *dev)
     serial_init_core(s);
     qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
 
-    memory_region_init_io(&isa->io, &serial_io_ops, s, "serial", 8);
-    isa_register_ioport(dev, &isa->io, isa->iobase);
+    memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
+    isa_register_ioport(dev, &s->io, isa->iobase);
     return 0;
 }
 
@@ -821,124 +821,45 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
 }
 
 /* Memory mapped interface */
-static uint32_t serial_mm_readb(void *opaque, target_phys_addr_t addr)
-{
-    SerialState *s = opaque;
-
-    return serial_ioport_read(s, addr >> s->it_shift) & 0xFF;
-}
-
-static void serial_mm_writeb(void *opaque, target_phys_addr_t addr,
-                             uint32_t value)
-{
-    SerialState *s = opaque;
-
-    serial_ioport_write(s, addr >> s->it_shift, value & 0xFF);
-}
-
-static uint32_t serial_mm_readw_be(void *opaque, target_phys_addr_t addr)
-{
-    SerialState *s = opaque;
-    uint32_t val;
-
-    val = serial_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
-    val = bswap16(val);
-    return val;
-}
-
-static uint32_t serial_mm_readw_le(void *opaque, target_phys_addr_t addr)
-{
-    SerialState *s = opaque;
-    uint32_t val;
-
-    val = serial_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
-    return val;
-}
-
-static void serial_mm_writew_be(void *opaque, target_phys_addr_t addr,
-                                uint32_t value)
-{
-    SerialState *s = opaque;
-
-    value = bswap16(value);
-    serial_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
-}
-
-static void serial_mm_writew_le(void *opaque, target_phys_addr_t addr,
-                                uint32_t value)
-{
-    SerialState *s = opaque;
-
-    serial_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
-}
-
-static uint32_t serial_mm_readl_be(void *opaque, target_phys_addr_t addr)
+static uint64_t serial_mm_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     SerialState *s = opaque;
-    uint32_t val;
-
-    val = serial_ioport_read(s, addr >> s->it_shift);
-    val = bswap32(val);
-    return val;
+    return serial_ioport_read(s, addr >> s->it_shift);
 }
 
-static uint32_t serial_mm_readl_le(void *opaque, target_phys_addr_t addr)
+static void serial_mm_write(void *opaque, target_phys_addr_t addr,
+                            uint64_t value, unsigned size)
 {
     SerialState *s = opaque;
-    uint32_t val;
-
-    val = serial_ioport_read(s, addr >> s->it_shift);
-    return val;
-}
-
-static void serial_mm_writel_be(void *opaque, target_phys_addr_t addr,
-                                uint32_t value)
-{
-    SerialState *s = opaque;
-
-    value = bswap32(value);
+    value &= ~0u >> (32 - (size * 8));
     serial_ioport_write(s, addr >> s->it_shift, value);
 }
 
-static void serial_mm_writel_le(void *opaque, target_phys_addr_t addr,
-                                uint32_t value)
-{
-    SerialState *s = opaque;
-
-    serial_ioport_write(s, addr >> s->it_shift, value);
-}
-
-static CPUReadMemoryFunc * const serial_mm_read_be[] = {
-    &serial_mm_readb,
-    &serial_mm_readw_be,
-    &serial_mm_readl_be,
-};
-
-static CPUWriteMemoryFunc * const serial_mm_write_be[] = {
-    &serial_mm_writeb,
-    &serial_mm_writew_be,
-    &serial_mm_writel_be,
-};
-
-static CPUReadMemoryFunc * const serial_mm_read_le[] = {
-    &serial_mm_readb,
-    &serial_mm_readw_le,
-    &serial_mm_readl_le,
-};
-
-static CPUWriteMemoryFunc * const serial_mm_write_le[] = {
-    &serial_mm_writeb,
-    &serial_mm_writew_le,
-    &serial_mm_writel_le,
+static const MemoryRegionOps serial_mm_ops[3] = {
+    [DEVICE_NATIVE_ENDIAN] = {
+        .read = serial_mm_read,
+        .write = serial_mm_write,
+        .endianness = DEVICE_NATIVE_ENDIAN,
+    },
+    [DEVICE_LITTLE_ENDIAN] = {
+        .read = serial_mm_read,
+        .write = serial_mm_write,
+        .endianness = DEVICE_LITTLE_ENDIAN,
+    },
+    [DEVICE_BIG_ENDIAN] = {
+        .read = serial_mm_read,
+        .write = serial_mm_write,
+        .endianness = DEVICE_BIG_ENDIAN,
+    },
 };
 
-SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
-                             qemu_irq irq, int baudbase,
-                             CharDriverState *chr, int ioregister,
-                             int be)
+SerialState *serial_mm_init(MemoryRegion *address_space,
+                            target_phys_addr_t base, int it_shift,
+                            qemu_irq irq, int baudbase,
+                            CharDriverState *chr, enum device_endian end)
 {
     SerialState *s;
-    int s_io_memory;
 
     s = g_malloc0(sizeof(SerialState));
 
@@ -950,18 +871,10 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     serial_init_core(s);
     vmstate_register(NULL, base, &vmstate_serial, s);
 
-    if (ioregister) {
-        if (be) {
-            s_io_memory = cpu_register_io_memory(serial_mm_read_be,
-                                                 serial_mm_write_be, s,
-                                                 DEVICE_NATIVE_ENDIAN);
-        } else {
-            s_io_memory = cpu_register_io_memory(serial_mm_read_le,
-                                                 serial_mm_write_le, s,
-                                                 DEVICE_NATIVE_ENDIAN);
-        }
-        cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
-    }
+    memory_region_init_io(&s->io, &serial_mm_ops[end], s,
+                          "serial", 8 << it_shift);
+    memory_region_add_subregion(address_space, base, &s->io);
+
     serial_update_msl(s);
     return s;
 }
index 1ed0a7e30908721f59d47f9f1225fc93e4bd70d4..a7ed6fadf1fb1f1d18c4e0a0006fe71030b8e072 100644 (file)
@@ -1385,8 +1385,8 @@ static void sm501_update_display(void *opaque)
        sm501_draw_crt(s);
 }
 
-void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
-                CharDriverState *chr)
+void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
+                uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr)
 {
     SM501State * s;
     DeviceState *dev;
@@ -1440,15 +1440,10 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
 
     /* bridge to serial emulation module */
     if (chr) {
-#ifdef TARGET_WORDS_BIGENDIAN
-        serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
+        serial_mm_init(address_space_mem,
+                       base + MMIO_BASE_OFFSET + SM501_UART0, 2,
                        NULL, /* TODO : chain irq to IRL */
-                       115200, chr, 1, 1);
-#else
-        serial_mm_init(base + MMIO_BASE_OFFSET + SM501_UART0, 2,
-                       NULL, /* TODO : chain irq to IRL */
-                       115200, chr, 1, 0);
-#endif
+                       115200, chr, DEVICE_NATIVE_ENDIAN);
     }
 
     /* create qemu graphic console */
index 3a8a85c1f194dcd8891ff834544681be2aa8876b..fc8c4984a7a668e497b0036230f43502a477de8c 100644 (file)
@@ -43,7 +43,7 @@ typedef struct {
     uint8_t data[NUM_PACKETS][2048];
     uint8_t int_level;
     uint8_t int_mask;
-    int mmio_index;
+    MemoryRegion mmio;
 } smc91c111_state;
 
 static const VMStateDescription vmstate_smc91c111 = {
@@ -717,16 +717,15 @@ static ssize_t smc91c111_receive(VLANClientState *nc, const uint8_t *buf, size_t
     return size;
 }
 
-static CPUReadMemoryFunc * const smc91c111_readfn[] = {
-    smc91c111_readb,
-    smc91c111_readw,
-    smc91c111_readl
-};
-
-static CPUWriteMemoryFunc * const smc91c111_writefn[] = {
-    smc91c111_writeb,
-    smc91c111_writew,
-    smc91c111_writel
+static const MemoryRegionOps smc91c111_mem_ops = {
+    /* The special case for 32 bit writes to 0xc means we can't just
+     * set .impl.min/max_access_size to 1, unfortunately
+     */
+    .old_mmio = {
+        .read = { smc91c111_readb, smc91c111_readw, smc91c111_readl, },
+        .write = { smc91c111_writeb, smc91c111_writew, smc91c111_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void smc91c111_cleanup(VLANClientState *nc)
@@ -747,11 +746,9 @@ static NetClientInfo net_smc91c111_info = {
 static int smc91c111_init1(SysBusDevice *dev)
 {
     smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev);
-
-    s->mmio_index = cpu_register_io_memory(smc91c111_readfn,
-                                           smc91c111_writefn, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 16, s->mmio_index);
+    memory_region_init_io(&s->mmio, &smc91c111_mem_ops, s,
+                          "smc91c111-mmio", 16);
+    sysbus_init_mmio_region(dev, &s->mmio);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
index 1265cee6d9f88834090e7aa6b41a7adbad62b12c..b1189755d30ba3aeedddf54466994e9409b952d1 100644 (file)
@@ -38,6 +38,9 @@
 #include "hw/spapr_vio.h"
 #include "hw/xics.h"
 
+#include "kvm.h"
+#include "kvm_ppc.h"
+
 #include <libfdt.h>
 
 #define KERNEL_LOAD_ADDR        0x00000000
 #define MAX_CPUS                256
 #define XICS_IRQS              1024
 
+#define PHANDLE_XICP            0x00001111
+
 sPAPREnvironment *spapr;
 
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
+{
+    uint32_t irq;
+    qemu_irq qirq;
+
+    if (hint) {
+        irq = hint;
+        /* FIXME: we should probably check for collisions somehow */
+    } else {
+        irq = spapr->next_irq++;
+    }
+
+    qirq = xics_find_qirq(spapr->icp, irq);
+    if (!qirq) {
+        return NULL;
+    }
+
+    if (irq_num) {
+        *irq_num = irq;
+    }
+
+    return qirq;
+}
+
 static void *spapr_create_fdt_skel(const char *cpu_model,
                                    target_phys_addr_t initrd_base,
                                    target_phys_addr_t initrd_size,
@@ -70,7 +99,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
     uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
     char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
-        "\0hcall-tce\0hcall-vio\0hcall-splpar";
+        "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
     uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
     int i;
     char *modelname;
@@ -137,6 +166,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
         char *nodename;
         uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
                            0xffffffff, 0xffffffff};
+        uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
+        uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
 
         if (asprintf(&nodename, "%s@%x", modelname, index) < 0) {
             fprintf(stderr, "Allocation failure\n");
@@ -155,10 +186,8 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
                                 env->dcache_line_size)));
         _FDT((fdt_property_cell(fdt, "icache-block-size",
                                 env->icache_line_size)));
-        _FDT((fdt_property_cell(fdt, "timebase-frequency", TIMEBASE_FREQ)));
-        /* Hardcode CPU frequency for now.  It's kind of arbitrary on
-         * full emu, for kvm we should copy it from the host */
-        _FDT((fdt_property_cell(fdt, "clock-frequency", 1000000000)));
+        _FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
+        _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
         _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
         _FDT((fdt_property(fdt, "ibm,pft-size",
                            pft_size_prop, sizeof(pft_size_prop))));
@@ -189,16 +218,18 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     _FDT((fdt_end_node(fdt)));
 
     /* interrupt controller */
-    _FDT((fdt_begin_node(fdt, "interrupt-controller@0")));
+    _FDT((fdt_begin_node(fdt, "interrupt-controller")));
 
     _FDT((fdt_property_string(fdt, "device_type",
                               "PowerPC-External-Interrupt-Presentation")));
     _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
-    _FDT((fdt_property_cell(fdt, "reg", 0)));
     _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
     _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
                        interrupt_server_ranges_prop,
                        sizeof(interrupt_server_ranges_prop))));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
+    _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
+    _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
 
     _FDT((fdt_end_node(fdt)));
 
@@ -298,7 +329,6 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     long kernel_size, initrd_size, fw_size;
     long pteg_shift = 17;
     char *filename;
-    int irq = 16;
 
     spapr = g_malloc(sizeof(*spapr));
     cpu_ppc_hypercall = emulate_spapr_hypercall;
@@ -330,19 +360,29 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(NULL, "ppc_spapr.ram", ram_size);
+    spapr->ram_limit = ram_size;
+    ram_offset = qemu_ram_alloc(NULL, "ppc_spapr.ram", spapr->ram_limit);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
     /* allocate hash page table.  For now we always make this 16mb,
      * later we should probably make it scale to the size of guest
      * RAM */
     spapr->htab_size = 1ULL << (pteg_shift + 7);
-    spapr->htab = g_malloc(spapr->htab_size);
+    spapr->htab = qemu_memalign(spapr->htab_size, spapr->htab_size);
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         env->external_htab = spapr->htab;
         env->htab_base = -1;
         env->htab_mask = spapr->htab_size - 1;
+
+        /* Tell KVM that we're in PAPR mode */
+        env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
+                             ((pteg_shift + 7) - 18);
+        env->spr[SPR_HIOR] = 0;
+
+        if (kvm_enabled()) {
+            kvmppc_set_papr(env);
+        }
     }
 
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
@@ -356,19 +396,19 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
     /* Set up Interrupt Controller */
     spapr->icp = xics_system_init(XICS_IRQS);
+    spapr->next_irq = 16;
 
     /* Set up VIO bus */
     spapr->vio_bus = spapr_vio_bus_init();
 
-    for (i = 0; i < MAX_SERIAL_PORTS; i++, irq++) {
+    for (i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
             spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i,
-                             serial_hds[i], xics_find_qirq(spapr->icp, irq),
-                             irq);
+                             serial_hds[i]);
         }
     }
 
-    for (i = 0; i < nb_nics; i++, irq++) {
+    for (i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
 
         if (!nd->model) {
@@ -376,8 +416,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
         }
 
         if (strcmp(nd->model, "ibmveth") == 0) {
-            spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd,
-                              xics_find_qirq(spapr->icp, irq), irq);
+            spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd);
         } else {
             fprintf(stderr, "pSeries (sPAPR) platform does not support "
                     "NIC model '%s' (only ibmveth is supported)\n",
@@ -387,9 +426,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
 
     for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
-        spapr_vscsi_create(spapr->vio_bus, 0x2000 + i,
-                           xics_find_qirq(spapr->icp, irq), irq);
-        irq++;
+        spapr_vscsi_create(spapr->vio_bus, 0x2000 + i);
     }
 
     if (kernel_filename) {
@@ -430,7 +467,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
                     "%ldM guest RAM\n", MIN_RAM_SLOF);
             exit(1);
         }
-        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "slof.bin");
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
         fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
         if (fw_size < 0) {
             hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
index 263691b6fbb3d16b7d7b09b644b49abfd74a4cf9..6657c336f62bedcae263241256a41ecfc9eb0870 100644 (file)
@@ -1,6 +1,8 @@
 #if !defined(__HW_SPAPR_H__)
 #define __HW_SPAPR_H__
 
+#include "hw/xics.h"
+
 struct VIOsPAPRBus;
 struct icp_state;
 
@@ -8,12 +10,15 @@ typedef struct sPAPREnvironment {
     struct VIOsPAPRBus *vio_bus;
     struct icp_state *icp;
 
+    target_phys_addr_t ram_limit;
     void *htab;
     long htab_size;
     target_phys_addr_t fdt_addr, rtas_addr;
     long rtas_size;
     void *fdt_skel;
     target_ulong entry_point;
+    int next_irq;
+    int rtc_offset;
 } sPAPREnvironment;
 
 #define H_SUCCESS         0
@@ -278,6 +283,8 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
 target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
                              target_ulong *args);
 
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num);
+
 static inline uint32_t rtas_ld(target_ulong phys, int n)
 {
     return ldl_be_phys(phys + 4*n);
index f7ead04a96b307628c70fe280340d413f4892800..84281be9e2d6d0b40e0ad41686a2b7a79cba57d4 100644 (file)
@@ -99,6 +99,8 @@ static target_ulong h_enter(CPUState *env, sPAPREnvironment *spapr,
     target_ulong pte_index = args[1];
     target_ulong pteh = args[2];
     target_ulong ptel = args[3];
+    target_ulong page_shift = 12;
+    target_ulong raddr;
     target_ulong i;
     uint8_t *hpte;
 
@@ -111,6 +113,7 @@ static target_ulong h_enter(CPUState *env, sPAPREnvironment *spapr,
 #endif
         if ((ptel & 0xff000) == 0) {
             /* 16M page */
+            page_shift = 24;
             /* lowest AVA bit must be 0 for 16M pages */
             if (pteh & 0x80) {
                 return H_PARAMETER;
@@ -120,12 +123,23 @@ static target_ulong h_enter(CPUState *env, sPAPREnvironment *spapr,
         }
     }
 
-    /* FIXME: bounds check the pa? */
+    raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
 
-    /* Check WIMG */
-    if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
-        return H_PARAMETER;
+    if (raddr < spapr->ram_limit) {
+        /* Regular RAM - should have WIMG=0010 */
+        if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
+            return H_PARAMETER;
+        }
+    } else {
+        /* Looks like an IO address */
+        /* FIXME: What WIMG combinations could be sensible for IO?
+         * For now we allow WIMG=010x, but are there others? */
+        /* FIXME: Should we check against registered IO addresses? */
+        if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
+            return H_PARAMETER;
+        }
     }
+
     pteh &= ~0x60ULL;
 
     if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
@@ -160,20 +174,26 @@ static target_ulong h_enter(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr,
-                             target_ulong opcode, target_ulong *args)
+enum {
+    REMOVE_SUCCESS = 0,
+    REMOVE_NOT_FOUND = 1,
+    REMOVE_PARM = 2,
+    REMOVE_HW = 3,
+};
+
+static target_ulong remove_hpte(CPUState *env, target_ulong ptex,
+                                target_ulong avpn,
+                                target_ulong flags,
+                                target_ulong *vp, target_ulong *rp)
 {
-    target_ulong flags = args[0];
-    target_ulong pte_index = args[1];
-    target_ulong avpn = args[2];
     uint8_t *hpte;
     target_ulong v, r, rb;
 
-    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
-        return H_PARAMETER;
+    if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return REMOVE_PARM;
     }
 
-    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
     while (!lock_hpte(hpte, HPTE_V_HVLOCK)) {
         /* We have no real concurrency in qemu soft-emulation, so we
          * will never actually have a contested lock */
@@ -188,14 +208,106 @@ static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr,
         ((flags & H_ANDCOND) && (v & avpn) != 0)) {
         stq_p(hpte, v & ~HPTE_V_HVLOCK);
         assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
-        return H_NOT_FOUND;
+        return REMOVE_NOT_FOUND;
     }
-    args[0] = v & ~HPTE_V_HVLOCK;
-    args[1] = r;
+    *vp = v & ~HPTE_V_HVLOCK;
+    *rp = r;
     stq_p(hpte, 0);
-    rb = compute_tlbie_rb(v, r, pte_index);
+    rb = compute_tlbie_rb(v, r, ptex);
     ppc_tlb_invalidate_one(env, rb);
     assert(!(ldq_p(hpte) & HPTE_V_HVLOCK));
+    return REMOVE_SUCCESS;
+}
+
+static target_ulong h_remove(CPUState *env, sPAPREnvironment *spapr,
+                             target_ulong opcode, target_ulong *args)
+{
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong avpn = args[2];
+    int ret;
+
+    ret = remove_hpte(env, pte_index, avpn, flags,
+                      &args[0], &args[1]);
+
+    switch (ret) {
+    case REMOVE_SUCCESS:
+        return H_SUCCESS;
+
+    case REMOVE_NOT_FOUND:
+        return H_NOT_FOUND;
+
+    case REMOVE_PARM:
+        return H_PARAMETER;
+
+    case REMOVE_HW:
+        return H_HARDWARE;
+    }
+
+    assert(0);
+}
+
+#define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
+#define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
+#define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
+#define   H_BULK_REMOVE_END            0xc000000000000000ULL
+#define H_BULK_REMOVE_CODE             0x3000000000000000ULL
+#define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
+#define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
+#define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
+#define   H_BULK_REMOVE_HW             0x3000000000000000ULL
+#define H_BULK_REMOVE_RC               0x0c00000000000000ULL
+#define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
+#define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
+#define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
+#define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
+#define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
+
+#define H_BULK_REMOVE_MAX_BATCH        4
+
+static target_ulong h_bulk_remove(CPUState *env, sPAPREnvironment *spapr,
+                                  target_ulong opcode, target_ulong *args)
+{
+    int i;
+
+    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
+        target_ulong *tsh = &args[i*2];
+        target_ulong tsl = args[i*2 + 1];
+        target_ulong v, r, ret;
+
+        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
+            break;
+        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
+            return H_PARAMETER;
+        }
+
+        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
+        *tsh |= H_BULK_REMOVE_RESPONSE;
+
+        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
+            *tsh |= H_BULK_REMOVE_PARM;
+            return H_PARAMETER;
+        }
+
+        ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
+                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
+                          &v, &r);
+
+        *tsh |= ret << 60;
+
+        switch (ret) {
+        case REMOVE_SUCCESS:
+            *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
+            break;
+
+        case REMOVE_PARM:
+            return H_PARAMETER;
+
+        case REMOVE_HW:
+            return H_HARDWARE;
+        }
+    }
+
     return H_SUCCESS;
 }
 
@@ -449,6 +561,67 @@ static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
                            nret, rtas_r3 + 12 + 4*nargs);
 }
 
+static target_ulong h_logical_load(CPUState *env, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    target_ulong size = args[0];
+    target_ulong addr = args[1];
+
+    switch (size) {
+    case 1:
+        args[0] = ldub_phys(addr);
+        return H_SUCCESS;
+    case 2:
+        args[0] = lduw_phys(addr);
+        return H_SUCCESS;
+    case 4:
+        args[0] = ldl_phys(addr);
+        return H_SUCCESS;
+    case 8:
+        args[0] = ldq_phys(addr);
+        return H_SUCCESS;
+    }
+    return H_PARAMETER;
+}
+
+static target_ulong h_logical_store(CPUState *env, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    target_ulong size = args[0];
+    target_ulong addr = args[1];
+    target_ulong val  = args[2];
+
+    switch (size) {
+    case 1:
+        stb_phys(addr, val);
+        return H_SUCCESS;
+    case 2:
+        stw_phys(addr, val);
+        return H_SUCCESS;
+    case 4:
+        stl_phys(addr, val);
+        return H_SUCCESS;
+    case 8:
+        stq_phys(addr, val);
+        return H_SUCCESS;
+    }
+    return H_PARAMETER;
+}
+
+static target_ulong h_logical_icbi(CPUState *env, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    /* Nothing to do on emulation, KVM will trap this in the kernel */
+    return H_SUCCESS;
+}
+
+static target_ulong h_logical_dcbf(CPUState *env, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    /* Nothing to do on emulation, KVM will trap this in the kernel */
+    return H_SUCCESS;
+}
+
 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
 
@@ -506,6 +679,9 @@ static void hypercall_init(void)
     spapr_register_hypercall(H_REMOVE, h_remove);
     spapr_register_hypercall(H_PROTECT, h_protect);
 
+    /* hcall-bulk */
+    spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
+
     /* hcall-dabr */
     spapr_register_hypercall(H_SET_DABR, h_set_dabr);
 
@@ -513,6 +689,18 @@ static void hypercall_init(void)
     spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
     spapr_register_hypercall(H_CEDE, h_cede);
 
+    /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
+     * here between the "CI" and the "CACHE" variants, they will use whatever
+     * mapping attributes qemu is using. When using KVM, the kernel will
+     * enforce the attributes more strongly
+     */
+    spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
+    spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
+    spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
+    spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
+    spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
+    spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
+
     /* qemu/KVM-PPC specific hcalls */
     spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 }
index c18efc7ee66ecb6f20fecd07d774597bc0aa66dd..abe12973e6fce6f0002f5fc9fe1fce33f4fc1572 100644 (file)
@@ -195,11 +195,9 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev)
     return 0;
 }
 
-void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd,
-                       qemu_irq qirq, uint32_t vio_irq_num)
+void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd)
 {
     DeviceState *dev;
-    VIOsPAPRDevice *sdev;
 
     dev = qdev_create(&bus->bus, "spapr-vlan");
     qdev_prop_set_uint32(dev, "reg", reg);
@@ -207,9 +205,6 @@ void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd,
     qdev_set_nic_properties(dev, nd);
 
     qdev_init_nofail(dev);
-    sdev = (VIOsPAPRDevice *)dev;
-    sdev->qirq = qirq;
-    sdev->vio_irq_num = vio_irq_num;
 }
 
 static int spapr_vlan_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
@@ -500,9 +495,7 @@ static VIOsPAPRDeviceInfo spapr_vlan = {
     .qdev.name = "spapr-vlan",
     .qdev.size = sizeof(VIOsPAPRVLANDevice),
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0x1000),
-        DEFINE_PROP_UINT32("dma-window", VIOsPAPRDevice, rtce_window_size,
-                           0x10000000),
+        DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x1000, 0x10000000),
         DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
         DEFINE_PROP_END_OF_LIST(),
     },
index 00c8ce5a155fd4ea61b1df8b9e3c5fc465dfed0a..d1ac74cfbdad39e763c2adfa6c89a64435614066 100644 (file)
@@ -67,7 +67,7 @@ static void rtas_get_time_of_day(sPAPREnvironment *spapr,
         return;
     }
 
-    qemu_get_timedate(&tm, 0);
+    qemu_get_timedate(&tm, spapr->rtc_offset);
 
     rtas_st(rets, 0, 0); /* Success */
     rtas_st(rets, 1, tm.tm_year + 1900);
@@ -79,6 +79,27 @@ static void rtas_get_time_of_day(sPAPREnvironment *spapr,
     rtas_st(rets, 7, 0); /* we don't do nanoseconds */
 }
 
+static void rtas_set_time_of_day(sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    struct tm tm;
+
+    tm.tm_year = rtas_ld(args, 0) - 1900;
+    tm.tm_mon = rtas_ld(args, 1) - 1;
+    tm.tm_mday = rtas_ld(args, 2);
+    tm.tm_hour = rtas_ld(args, 3);
+    tm.tm_min = rtas_ld(args, 4);
+    tm.tm_sec = rtas_ld(args, 5);
+
+    /* Just generate a monitor event for the change */
+    rtc_change_mon_event(&tm);
+    spapr->rtc_offset = qemu_timedate_diff(&tm);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
 static void rtas_power_off(sPAPREnvironment *spapr,
                            uint32_t token, uint32_t nargs, target_ulong args,
                            uint32_t nret, target_ulong rets)
@@ -271,6 +292,7 @@ static void register_core_rtas(void)
 {
     spapr_rtas_register("display-character", rtas_display_character);
     spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
+    spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
     spapr_rtas_register("power-off", rtas_power_off);
     spapr_rtas_register("query-cpu-stopped-state",
                         rtas_query_cpu_stopped_state);
index ce6558bb7ed258cac6d322365e494596b53551d4..35818e18f1e0a16d1b41d9ff42fc375336db10c2 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
+#include "hw/xics.h"
 
 #ifdef CONFIG_FDT
 #include <libfdt.h>
 static struct BusInfo spapr_vio_bus_info = {
     .name       = "spapr-vio",
     .size       = sizeof(VIOsPAPRBus),
+    .props = (Property[]) {
+        DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \
+        DEFINE_PROP_END_OF_LIST(),
+    },
 };
 
 VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
@@ -603,6 +608,11 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
 
     dev->qdev.id = id;
 
+    dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
+    if (!dev->qirq) {
+        return -1;
+    }
+
     rtce_init(dev);
 
     return info->init(dev);
index 603a8c43a38bce0c0fb60d950c110116d1114859..4fe5f742c20b127b114105763063682b82131949 100644 (file)
@@ -60,6 +60,11 @@ typedef struct VIOsPAPRDevice {
     VIOsPAPR_CRQ crq;
 } VIOsPAPRDevice;
 
+#define DEFINE_SPAPR_PROPERTIES(type, field, default_reg, default_dma_window) \
+        DEFINE_PROP_UINT32("reg", type, field.reg, default_reg), \
+        DEFINE_PROP_UINT32("dma-window", type, field.rtce_window_size, \
+                           default_dma_window)
+
 typedef struct VIOsPAPRBus {
     BusState bus;
 } VIOsPAPRBus;
@@ -98,15 +103,9 @@ uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr);
 int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
 
 void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
-void spapr_vty_create(VIOsPAPRBus *bus,
-                      uint32_t reg, CharDriverState *chardev,
-                      qemu_irq qirq, uint32_t vio_irq_num);
-
-void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd,
-                       qemu_irq qirq, uint32_t vio_irq_num);
-
-void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg,
-                        qemu_irq qirq, uint32_t vio_irq_num);
+void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
+void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
+void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg);
 
 int spapr_tce_set_bypass(uint32_t unit, uint32_t enable);
 void spapr_vio_quiesce(void);
index fc9ac6ab50c8500ff8766d3d6896ce97cb6d3d0e..e8426d7c5e9ace9366811e81392cab484f71d367 100644 (file)
@@ -483,7 +483,6 @@ static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status)
     if (status == CHECK_CONDITION) {
         req->senselen = scsi_req_get_sense(req->sreq, req->sense,
                                            sizeof(req->sense));
-        status = 0;
         dprintf("VSCSI: Sense data, %d bytes:\n", len);
         dprintf("       %02x  %02x  %02x  %02x  %02x  %02x  %02x  %02x\n",
                 req->sense[0], req->sense[1], req->sense[2], req->sense[3],
@@ -893,20 +892,14 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev)
     return 0;
 }
 
-void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg,
-                        qemu_irq qirq, uint32_t vio_irq_num)
+void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg)
 {
     DeviceState *dev;
-    VIOsPAPRDevice *sdev;
 
     dev = qdev_create(&bus->bus, "spapr-vscsi");
     qdev_prop_set_uint32(dev, "reg", reg);
 
     qdev_init_nofail(dev);
-
-    sdev = (VIOsPAPRDevice *)dev;
-    sdev->qirq = qirq;
-    sdev->vio_irq_num = vio_irq_num;
 }
 
 static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
@@ -936,9 +929,7 @@ static VIOsPAPRDeviceInfo spapr_vscsi = {
     .qdev.name = "spapr-vscsi",
     .qdev.size = sizeof(VSCSIState),
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0x2000),
-        DEFINE_PROP_UINT32("dma-window", VIOsPAPRDevice,
-                           rtce_window_size, 0x10000000),
+        DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x2000, 0x10000000),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
index f5046d918303592c5fb46f1d127ee86a871a4be8..a9d4b035e28015a355ed70dc1e4ebd3a31dd5214 100644 (file)
@@ -115,20 +115,14 @@ static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
-void spapr_vty_create(VIOsPAPRBus *bus,
-                      uint32_t reg, CharDriverState *chardev,
-                      qemu_irq qirq, uint32_t vio_irq_num)
+void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev)
 {
     DeviceState *dev;
-    VIOsPAPRDevice *sdev;
 
     dev = qdev_create(&bus->bus, "spapr-vty");
     qdev_prop_set_uint32(dev, "reg", reg);
     qdev_prop_set_chr(dev, "chardev", chardev);
     qdev_init_nofail(dev);
-    sdev = (VIOsPAPRDevice *)dev;
-    sdev->qirq = qirq;
-    sdev->vio_irq_num = vio_irq_num;
 }
 
 static void vty_hcalls(VIOsPAPRBus *bus)
@@ -146,7 +140,7 @@ static VIOsPAPRDeviceInfo spapr_vty = {
     .qdev.name = "spapr-vty",
     .qdev.size = sizeof(VIOsPAPRVTYDevice),
     .qdev.props = (Property[]) {
-        DEFINE_PROP_UINT32("reg", VIOsPAPRDevice, reg, 0),
+        DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0, 0),
         DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
         DEFINE_PROP_END_OF_LIST(),
     },
index 0adae596b571c393da2d2bcb2a08142637e55bb7..6f8a94ceb3f13291ea4df3649cc6d5b616960644 100644 (file)
@@ -24,6 +24,7 @@
 #include "boards.h"
 #include "blockdev.h"
 #include "sysbus.h"
+#include "exec-memory.h"
 
 #undef REG_FMT
 #define REG_FMT                        "0x%02lx"
@@ -896,12 +897,13 @@ static void spitz_common_init(ram_addr_t ram_size,
 {
     PXA2xxState *cpu;
     DeviceState *scp0, *scp1 = NULL;
+    MemoryRegion *address_space_mem = get_system_memory();
 
     if (!cpu_model)
         cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
 
     /* Setup CPU & memory */
-    cpu = pxa270_init(spitz_binfo.ram_size, cpu_model);
+    cpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
 
     sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
index fbef350a4480ea7b628d17483e0a9c1d284e3656..88c633d491e38c990fc3f8b8b3b2ff5642ad9377 100644 (file)
@@ -38,6 +38,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 //#define DEBUG_IRQ
 //#define DEBUG_EBUS
@@ -735,7 +736,8 @@ static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
     return env;
 }
 
-static void sun4uv_init(ram_addr_t RAM_size,
+static void sun4uv_init(MemoryRegion *address_space_mem,
+                        ram_addr_t RAM_size,
                         const char *boot_devices,
                         const char *kernel_filename, const char *kernel_cmdline,
                         const char *initrd_filename, const char *cpu_model,
@@ -770,8 +772,8 @@ static void sun4uv_init(ram_addr_t RAM_size,
 
     i = 0;
     if (hwdef->console_serial_base) {
-        serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200,
-                       serial_hds[i], 1, 1);
+        serial_mm_init(address_space_mem, hwdef->console_serial_base, 0,
+                       NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
         i++;
     }
     for(; i < MAX_SERIAL_PORTS; i++) {
@@ -875,7 +877,7 @@ static void sun4u_init(ram_addr_t RAM_size,
                        const char *kernel_filename, const char *kernel_cmdline,
                        const char *initrd_filename, const char *cpu_model)
 {
-    sun4uv_init(RAM_size, boot_devices, kernel_filename,
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
                 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
 }
 
@@ -885,7 +887,7 @@ static void sun4v_init(ram_addr_t RAM_size,
                        const char *kernel_filename, const char *kernel_cmdline,
                        const char *initrd_filename, const char *cpu_model)
 {
-    sun4uv_init(RAM_size, boot_devices, kernel_filename,
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
                 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
 }
 
@@ -895,7 +897,7 @@ static void niagara_init(ram_addr_t RAM_size,
                          const char *kernel_filename, const char *kernel_cmdline,
                          const char *initrd_filename, const char *cpu_model)
 {
-    sun4uv_init(RAM_size, boot_devices, kernel_filename,
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
                 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
 }
 
index 7b407f4f64c432a74c454d0dcab941625a62eb32..92702d148a6891a3563feb5c1d7c9d62c9cba00a 100644 (file)
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -20,6 +20,7 @@
 #include "ssi.h"
 #include "blockdev.h"
 #include "sysbus.h"
+#include "exec-memory.h"
 
 #define TOSA_RAM    0x04000000
 #define TOSA_ROM       0x00800000
@@ -206,6 +207,7 @@ static void tosa_init(ram_addr_t ram_size,
                 const char *kernel_filename, const char *kernel_cmdline,
                 const char *initrd_filename, const char *cpu_model)
 {
+    MemoryRegion *address_space_mem = get_system_memory();
     PXA2xxState *cpu;
     TC6393xbState *tmio;
     DeviceState *scp0, *scp1;
@@ -213,7 +215,7 @@ static void tosa_init(ram_addr_t ram_size,
     if (!cpu_model)
         cpu_model = "pxa255";
 
-    cpu = pxa255_init(tosa_binfo.ram_size);
+    cpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
 
     cpu_register_physical_memory(0, TOSA_ROM,
                     qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
index 7459b0bbe901147de97637dfee4b0fb05510c216..d31a2046184bad2dd3d3612d77b11f28e9b11252 100644 (file)
@@ -34,6 +34,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "qemu-log.h"
+#include "exec-memory.h"
 
 #include "ppc.h"
 #include "ppc4xx.h"
@@ -81,7 +82,6 @@ static void mmubooke_create_initial_mapping(CPUState *env,
 static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size,
                                     int do_init,
                                     const char *cpu_model,
-                                    clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
                                     uint32_t sysclk)
 {
     CPUState *env;
@@ -93,11 +93,7 @@ static CPUState *ppc440_init_xilinx(ram_addr_t *ram_size,
         exit(1);
     }
 
-    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
-    cpu_clk->opaque = env;
-    /* Set time-base frequency to sysclk */
-    tb_clk->cb = ppc_emb_timers_init(env, sysclk, PPC_INTERRUPT_DECR);
-    tb_clk->opaque = env;
+    ppc_booke_timers_init(env, sysclk, 0/* no flags */);
 
     ppc_dcr_init(env, NULL, NULL);
 
@@ -191,13 +187,13 @@ static void virtex_init(ram_addr_t ram_size,
                         const char *kernel_cmdline,
                         const char *initrd_filename, const char *cpu_model)
 {
+    MemoryRegion *address_space_mem = get_system_memory();
     DeviceState *dev;
     CPUState *env;
     target_phys_addr_t ram_base = 0;
     DriveInfo *dinfo;
     ram_addr_t phys_ram;
     qemu_irq irq[32], *cpu_irq;
-    clk_setup_t clk_setup[7];
     int kernel_size;
     int i;
 
@@ -207,8 +203,7 @@ static void virtex_init(ram_addr_t ram_size,
     }
 
     memset(clk_setup, 0, sizeof(clk_setup));
-    env = ppc440_init_xilinx(&ram_size, 1, cpu_model, &clk_setup[0],
-                             &clk_setup[1], 400000000);
+    env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
     qemu_register_reset(main_cpu_reset, env);
 
     phys_ram = qemu_ram_alloc(NULL, "ram", ram_size);
@@ -226,7 +221,8 @@ static void virtex_init(ram_addr_t ram_size,
         irq[i] = qdev_get_gpio_in(dev, i);
     }
 
-    serial_mm_init(0x83e01003ULL, 2, irq[9], 115200, serial_hds[0], 1, 0);
+    serial_mm_init(address_space_mem, 0x83e01003ULL, 2, irq[9], 115200,
+                   serial_hds[0], DEVICE_LITTLE_ENDIAN);
 
     /* 2 timers at irq 2 @ 62 Mhz.  */
     xilinx_timer_create(0x83c00000, irq[3], 2, 62 * 1000000);
index 80e064eaa39b71c0975ec12f5a718256ca5f1c45..1c5eaa4135c31e5299eb1848c4a98b330187d995 100644 (file)
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -185,17 +185,17 @@ static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
         && (nr < (ics->offset + ics->nr_irqs));
 }
 
-static void ics_set_irq_msi(void *opaque, int nr, int val)
+static void ics_set_irq_msi(void *opaque, int srcno, int val)
 {
     struct ics_state *ics = (struct ics_state *)opaque;
-    struct ics_irq_state *irq = ics->irqs + nr;
+    struct ics_irq_state *irq = ics->irqs + srcno;
 
     if (val) {
         if (irq->priority == 0xff) {
             irq->masked_pending = 1;
             /* masked pending */ ;
         } else  {
-            icp_irq(ics->icp, irq->server, nr + ics->offset, irq->priority);
+            icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
         }
     }
 }
@@ -227,7 +227,7 @@ static void ics_resend_msi(struct ics_state *ics)
 static void ics_write_xive_msi(struct ics_state *ics, int nr, int server,
                                uint8_t priority)
 {
-    struct ics_irq_state *irq = ics->irqs + nr;
+    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
 
     irq->server = server;
     irq->priority = priority;
@@ -237,7 +237,7 @@ static void ics_write_xive_msi(struct ics_state *ics, int nr, int server,
     }
 
     irq->masked_pending = 0;
-    icp_irq(ics->icp, server, nr + ics->offset, priority);
+    icp_irq(ics->icp, server, nr, priority);
 }
 
 static void ics_reject(struct ics_state *ics, int nr)
@@ -332,7 +332,7 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
         return;
     }
 
-    ics_write_xive_msi(ics, nr - ics->offset, server, priority);
+    ics_write_xive_msi(ics, nr, server, priority);
 
     rtas_st(rets, 0, 0); /* Success */
 }
@@ -386,7 +386,7 @@ static void rtas_int_off(sPAPREnvironment *spapr, uint32_t token,
     struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
 
     irq->saved_priority = irq->priority;
-    ics_write_xive_msi(xics, nr - xics->offset, irq->server, 0xff);
+    ics_write_xive_msi(xics, nr, irq->server, 0xff);
 #endif
 
     rtas_st(rets, 0, 0); /* Success */
@@ -416,8 +416,7 @@ static void rtas_int_on(sPAPREnvironment *spapr, uint32_t token,
 #if 0
     struct ics_irq_state *irq = xics->irqs + (nr - xics->offset);
 
-    ics_write_xive_msi(xics, nr - xics->offset,
-                       irq->server, irq->saved_priority);
+    ics_write_xive_msi(xics, nr, irq->server, irq->saved_priority);
 #endif
 
     rtas_st(rets, 0, 0); /* Success */
diff --git a/hw/z2.c b/hw/z2.c
index b6ae608657b0666eede78e888ce2c8d48a7d47cb..a03bb33d1b721ee75be3e400ff59922c1c462035 100644 (file)
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -20,6 +20,7 @@
 #include "blockdev.h"
 #include "console.h"
 #include "audio/audio.h"
+#include "exec-memory.h"
 
 #ifdef DEBUG_Z2
 #define DPRINTF(fmt, ...) \
@@ -277,6 +278,7 @@ static void z2_init(ram_addr_t ram_size,
                 const char *kernel_filename, const char *kernel_cmdline,
                 const char *initrd_filename, const char *cpu_model)
 {
+    MemoryRegion *address_space_mem = get_system_memory();
     uint32_t sector_len = 0x10000;
     PXA2xxState *cpu;
     DriveInfo *dinfo;
@@ -290,7 +292,7 @@ static void z2_init(ram_addr_t ram_size,
     }
 
     /* Setup CPU & memory */
-    cpu = pxa270_init(z2_binfo.ram_size, cpu_model);
+    cpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
 
 #ifdef TARGET_WORDS_BIGENDIAN
     be = 1;
index 777d307c717f1b4c707640a5e101e058d095d8ea..fb3fddcd87f6f7918b0720d5a366df5d948de16b 100644 (file)
 
 #include <linux/types.h>
 
+/* Select powerpc specific features in <linux/kvm.h> */
+#define __KVM_HAVE_SPAPR_TCE
+#define __KVM_HAVE_PPC_SMT
+
 struct kvm_regs {
        __u64 pc;
        __u64 cr;
@@ -272,4 +276,57 @@ struct kvm_guest_debug_arch {
 #define KVM_INTERRUPT_UNSET    -2U
 #define KVM_INTERRUPT_SET_LEVEL        -3U
 
+#define KVM_CPU_440            1
+#define KVM_CPU_E500V2         2
+#define KVM_CPU_3S_32          3
+#define KVM_CPU_3S_64          4
+
+/* for KVM_CAP_SPAPR_TCE */
+struct kvm_create_spapr_tce {
+       __u64 liobn;
+       __u32 window_size;
+};
+
+/* for KVM_ALLOCATE_RMA */
+struct kvm_allocate_rma {
+       __u64 rma_size;
+};
+
+struct kvm_book3e_206_tlb_entry {
+       __u32 mas8;
+       __u32 mas1;
+       __u64 mas2;
+       __u64 mas7_3;
+};
+
+struct kvm_book3e_206_tlb_params {
+       /*
+        * For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
+        *
+        * - The number of ways of TLB0 must be a power of two between 2 and
+        *   16.
+        * - TLB1 must be fully associative.
+        * - The size of TLB0 must be a multiple of the number of ways, and
+        *   the number of sets must be a power of two.
+        * - The size of TLB1 may not exceed 64 entries.
+        * - TLB0 supports 4 KiB pages.
+        * - The page sizes supported by TLB1 are as indicated by
+        *   TLB1CFG (if MMUCFG[MAVN] = 0) or TLB1PS (if MMUCFG[MAVN] = 1)
+        *   as returned by KVM_GET_SREGS.
+        * - TLB2 and TLB3 are reserved, and their entries in tlb_sizes[]
+        *   and tlb_ways[] must be zero.
+        *
+        * tlb_ways[n] = tlb_sizes[n] means the array is fully associative.
+        *
+        * KVM will adjust TLBnCFG based on the sizes configured here,
+        * though arrays greater than 2048 entries will have TLBnCFG[NENTRY]
+        * set to zero.
+        */
+       __u32 tlb_sizes[4];
+       __u32 tlb_ways[4];
+       __u32 reserved[8];
+};
+
+#define KVM_ONE_REG_PPC_HIOR   KVM_ONE_REG_PPC | 0x100
+
 #endif /* __LINUX_KVM_POWERPC_H */
index 834d71ea1ff5fcc582f6f9f19e8356be11aa238c..f2ac46a2a2f8682b49b29450bd1c61eb12594ebd 100644 (file)
@@ -21,6 +21,7 @@
  */
 #define KVM_FEATURE_CLOCKSOURCE2        3
 #define KVM_FEATURE_ASYNC_PF           4
+#define KVM_FEATURE_STEAL_TIME         5
 
 /* The last 8 bits are used to indicate how to interpret the flags field
  * in pvclock structure. If no bits are set, all flags are ignored.
 #define MSR_KVM_WALL_CLOCK  0x11
 #define MSR_KVM_SYSTEM_TIME 0x12
 
+#define KVM_MSR_ENABLED 1
 /* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
 #define MSR_KVM_WALL_CLOCK_NEW  0x4b564d00
 #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
 #define MSR_KVM_ASYNC_PF_EN 0x4b564d02
+#define MSR_KVM_STEAL_TIME  0x4b564d03
+
+struct kvm_steal_time {
+       __u64 steal;
+       __u32 version;
+       __u32 flags;
+       __u32 pad[12];
+};
+
+#define KVM_STEAL_ALIGNMENT_BITS 5
+#define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
+#define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
 
 #define KVM_MAX_MMU_OP_BATCH           32
 
index fc63b739964b0815ccc9a4316e4f00646ae5e597..a8761d3be6c49a28bf4f4c1a9fec27427c1af3dc 100644 (file)
@@ -161,6 +161,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_NMI              16
 #define KVM_EXIT_INTERNAL_ERROR   17
 #define KVM_EXIT_OSI              18
+#define KVM_EXIT_PAPR_HCALL      19
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 #define KVM_INTERNAL_ERROR_EMULATION 1
@@ -264,6 +265,11 @@ struct kvm_run {
                struct {
                        __u64 gprs[32];
                } osi;
+               struct {
+                       __u64 nr;
+                       __u64 ret;
+                       __u64 args[9];
+               } papr_hcall;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -457,7 +463,7 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_VAPIC 6
 #define KVM_CAP_EXT_CPUID 7
 #define KVM_CAP_CLOCKSOURCE 8
-#define KVM_CAP_NR_VCPUS 9       /* returns max vcpus per vm */
+#define KVM_CAP_NR_VCPUS 9       /* returns recommended max vcpus per vm */
 #define KVM_CAP_NR_MEMSLOTS 10   /* returns max memory slots per vm */
 #define KVM_CAP_PIT 11
 #define KVM_CAP_NOP_IO_DELAY 12
@@ -544,6 +550,14 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_TSC_CONTROL 60
 #define KVM_CAP_GET_TSC_KHZ 61
 #define KVM_CAP_PPC_BOOKE_SREGS 62
+#define KVM_CAP_SPAPR_TCE 63
+#define KVM_CAP_PPC_SMT 64
+#define KVM_CAP_PPC_RMA        65
+#define KVM_CAP_MAX_VCPUS 66       /* returns max vcpus per vm */
+#define KVM_CAP_PPC_HIOR 67
+#define KVM_CAP_PPC_PAPR 68
+#define KVM_CAP_SW_TLB 69
+#define KVM_CAP_ONE_REG 70
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -623,6 +637,49 @@ struct kvm_clock_data {
        __u32 pad[9];
 };
 
+#define KVM_MMU_FSL_BOOKE_NOHV         0
+#define KVM_MMU_FSL_BOOKE_HV           1
+
+struct kvm_config_tlb {
+       __u64 params;
+       __u64 array;
+       __u32 mmu_type;
+       __u32 array_len;
+};
+
+struct kvm_dirty_tlb {
+       __u64 bitmap;
+       __u32 num_dirty;
+};
+
+/* Available with KVM_CAP_ONE_REG */
+
+#define KVM_ONE_REG_GENERIC            0x0000000000000000ULL
+
+/*
+ * Architecture specific registers are to be defined in arch headers and
+ * ORed with the arch identifier.
+ */
+#define KVM_ONE_REG_PPC                        0x1000000000000000ULL
+#define KVM_ONE_REG_X86                        0x2000000000000000ULL
+#define KVM_ONE_REG_IA64               0x3000000000000000ULL
+#define KVM_ONE_REG_ARM                        0x4000000000000000ULL
+#define KVM_ONE_REG_S390               0x5000000000000000ULL
+
+struct kvm_one_reg {
+       __u64 id;
+       union {
+               __u8 reg8;
+               __u16 reg16;
+               __u32 reg32;
+               __u64 reg64;
+               __u8 reg128[16];
+               __u8 reg256[32];
+               __u8 reg512[64];
+               __u8 reg1024[128];
+       } u;
+};
+
 /*
  * ioctls for VM fds
  */
@@ -746,6 +803,14 @@ struct kvm_clock_data {
 /* Available with KVM_CAP_XCRS */
 #define KVM_GET_XCRS             _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 #define KVM_SET_XCRS             _IOW(KVMIO,  0xa7, struct kvm_xcrs)
+#define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_SW_TLB */
+#define KVM_DIRTY_TLB            _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
+/* Available with KVM_CAP_ONE_REG */
+#define KVM_GET_ONE_REG                  _IOWR(KVMIO, 0xab, struct kvm_one_reg)
+#define KVM_SET_ONE_REG                  _IOW(KVMIO,  0xac, struct kvm_one_reg)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
 
@@ -773,20 +838,14 @@ struct kvm_assigned_pci_dev {
 
 struct kvm_assigned_irq {
        __u32 assigned_dev_id;
-       __u32 host_irq;
+       __u32 host_irq; /* ignored (legacy field) */
        __u32 guest_irq;
        __u32 flags;
        union {
-               struct {
-                       __u32 addr_lo;
-                       __u32 addr_hi;
-                       __u32 data;
-               } guest_msi;
                __u32 reserved[12];
        };
 };
 
-
 struct kvm_assigned_msix_nr {
        __u32 assigned_dev_id;
        __u16 entry_nr;
index 7bdcf93c1dba4b683ee177ad8148596e18d5005a..b315e27a9c9e54f507f8a4ff7bf0d658b75736ad 100644 (file)
@@ -26,3 +26,4 @@
 #include <asm/kvm_para.h>
 
 #endif /* __LINUX_KVM_PARA_H */
+
index 89276eb6a5e415950da9f2f3ef851f180c0cdcec..40c5eb18464646df865451917abbb74cd4116d8d 100644 (file)
@@ -1274,10 +1274,7 @@ setup_return(CPUState *env, struct target_sigaction *ka,
 
                if (__put_user(retcodes[idx], rc))
                        return 1;
-#if 0
-               flush_icache_range((abi_ulong)rc,
-                                  (abi_ulong)(rc + 1));
-#endif
+
                retcode = rc_addr + thumb;
        }
 
index c22687924fdae17fad0c5e1246fea5d321a83223..31b212aa6b75917f948adeb0ec35ea611e5e92a9 100644 (file)
--- a/monitor.c
+++ b/monitor.c
 #include "json-parser.h"
 #include "osdep.h"
 #include "cpu.h"
+#include "trace.h"
 #include "trace/control.h"
 #ifdef CONFIG_TRACE_SIMPLE
 #include "trace/simple.h"
 #endif
-#include "trace/control.h"
 #include "ui/qemu-spice.h"
 #include "memory.h"
 #include "qmp-commands.h"
@@ -373,6 +373,8 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
 {
     QDict *qmp;
 
+    trace_monitor_protocol_emitter(mon);
+
     qmp = qdict_new();
 
     if (!monitor_has_error(mon)) {
@@ -609,7 +611,7 @@ static void do_trace_event_set_state(Monitor *mon, const QDict *qdict)
     }
 }
 
-#ifdef CONFIG_SIMPLE_TRACE
+#ifdef CONFIG_TRACE_SIMPLE
 static void do_trace_file(Monitor *mon, const QDict *qdict)
 {
     const char *op = qdict_get_try_str(qdict, "op");
@@ -2366,7 +2368,7 @@ static void tlb_info(Monitor *mon)
 
 #endif
 
-#if defined(TARGET_SPARC)
+#if defined(TARGET_SPARC) || defined(TARGET_PPC)
 static void tlb_info(Monitor *mon)
 {
     CPUState *env1 = mon_get_cpu();
@@ -2812,7 +2814,8 @@ static const mon_cmd_t info_cmds[] = {
         .user_print = do_pci_info_print,
         .mhandler.info_new = do_pci_info,
     },
-#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC)
+#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
+    defined(TARGET_PPC)
     {
         .name       = "tlb",
         .args_type  = "",
@@ -4889,6 +4892,7 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
     qobject_incref(mon->mc->id);
 
     cmd_name = qdict_get_str(input, "execute");
+    trace_handle_qmp_command(mon, cmd_name);
     if (invalid_qmp_mode(mon, cmd_name)) {
         qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
         goto err_out;
index 02651fe224f690fd8b05e469b2f2202591c779e1..4d1d816fdbe899a3e5cda6cef0e19df884681eb4 100644 (file)
@@ -32,3 +32,6 @@
 - The S390 zipl loader is an addition to the official IBM s390-tools
   package. That fork is maintained in its own git repository at:
   git://repo.or.cz/s390-tools.git
+
+- The sources for the Alpha palcode image is available from:
+  git://repo.or.cz/qemu-palcode.git
index ae318b1fe83846cc2e133951a3666fcfcdf87f79..c6d302153c7407d5d0127be29b0c35f80e47f8fb 100644 (file)
Binary files a/pc-bios/mpc8544ds.dtb and b/pc-bios/mpc8544ds.dtb differ
index a88b47c11bfd836ac58c796c181be33a59de3a27..7eb31604fc433e8bb69b35a89a143ede5d45d941 100644 (file)
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-
-               PowerPC,8544@0 {
-                       device_type = "cpu";
-                       reg = <0x0>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <0x8000>;                // L1, 32K
-                       i-cache-size = <0x8000>;                // L1, 32K
-                       timebase-frequency = <0>;
-                       bus-frequency = <0>;
-                       clock-frequency = <0>;
-               };
        };
 
        memory {
diff --git a/pc-bios/palcode-clipper b/pc-bios/palcode-clipper
new file mode 100755 (executable)
index 0000000..a92372c
Binary files /dev/null and b/pc-bios/palcode-clipper differ
index 0059ee53acea5ca2607500537c6e9fedfe6d6ca3..0a7c0dd0c8785a58460f6dd346a2d8942a14e49a 100644 (file)
--- a/ppc64.ld
+++ b/ppc64.ld
@@ -81,8 +81,8 @@ SECTIONS
   .sdata2         : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) }
   .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
   .eh_frame_hdr : { *(.eh_frame_hdr) }
-*(.gcc_except_table.*) } /* Adjust the address for the data segment.  We want to
-adjust up to +     the same address within the page on the next page up.  */
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
   . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN
 (0x10000, 0x1000);   /* Exception handling  */
   .eh_frame       : { KEEP (*(.eh_frame)) }
diff --git a/roms/qemu-palcode b/roms/qemu-palcode
new file mode 160000 (submodule)
index 0000000..7abb12f
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 7abb12f60eb3069019e9497e193733d77d8f0722
index c2e7bb31eff0ac4791b19847f7f1255c9cd9cffd..9d61d45ab610e9adf0ea985fbab2472f73e956f8 100644 (file)
@@ -265,6 +265,10 @@ struct CPUAlphaState {
     uint64_t scratch[24];
 #endif
 
+    /* This alarm doesn't exist in real hardware; we wish it did.  */
+    struct QEMUTimer *alarm_timer;
+    uint64_t alarm_expire;
+
 #if TARGET_LONG_BITS > HOST_LONG_BITS
     /* temporary fixed-point registers
      * used to emulate 64 bits target on 32 bits hosts
index 2dec57e44b25f31b329464e681ccc93fa8700f48..b693ceea9712c3bb31b9042bdf64e018b33d6f45 100644 (file)
@@ -113,6 +113,11 @@ DEF_HELPER_2(stq_c_phys, i64, i64, i64)
 
 DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void)
 DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64)
+
+DEF_HELPER_1(halt, void, i64);
+
+DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64)
+DEF_HELPER_FLAGS_1(set_alarm, TCG_CALL_CONST, void, i64)
 #endif
 
 #include "def-helper.h"
index d8945dcbcac989c94a7837179586fd9568d6d69c..cc102dbd633bd21c4614cc52d6f4cbbfef8400d6 100644 (file)
@@ -22,6 +22,7 @@
 #include "host-utils.h"
 #include "softfloat.h"
 #include "helper.h"
+#include "sysemu.h"
 #include "qemu-timer.h"
 
 #define FP_STATUS (env->fp_status)
@@ -1218,6 +1219,30 @@ void helper_tbis(uint64_t p)
 {
     tlb_flush_page(env, p);
 }
+
+void helper_halt(uint64_t restart)
+{
+    if (restart) {
+        qemu_system_reset_request();
+    } else {
+        qemu_system_shutdown_request();
+    }
+}
+
+uint64_t helper_get_time(void)
+{
+    return qemu_get_clock_ns(rtc_clock);
+}
+
+void helper_set_alarm(uint64_t expire)
+{
+    if (expire) {
+        env->alarm_expire = expire;
+        qemu_mod_timer(env->alarm_timer, expire);
+    } else {
+        qemu_del_timer(env->alarm_timer);
+    }
+}
 #endif
 
 /*****************************************************************************/
index 1e224a2152bef0b25a15c59f9dd5454f5cf6a426..a961159d5d8004ae2698b6dce2b473e589b183b5 100644 (file)
@@ -1590,18 +1590,34 @@ static int cpu_pr_data(int pr)
         return offsetof(CPUAlphaState, shadow[pr - 32]);
     case 40 ... 63:
         return offsetof(CPUAlphaState, scratch[pr - 40]);
+
+    case 251:
+        return offsetof(CPUAlphaState, alarm_expire);
     }
     return 0;
 }
 
-static void gen_mfpr(int ra, int regno)
+static ExitStatus gen_mfpr(int ra, int regno)
 {
     int data = cpu_pr_data(regno);
 
     /* In our emulated PALcode, these processor registers have no
        side effects from reading.  */
     if (ra == 31) {
-        return;
+        return NO_EXIT;
+    }
+
+    if (regno == 250) {
+        /* WALL_TIME */
+        if (use_icount) {
+            gen_io_start();
+            gen_helper_get_time(cpu_ir[ra]);
+            gen_io_end();
+            return EXIT_PC_STALE;
+        } else {
+            gen_helper_get_time(cpu_ir[ra]);
+            return NO_EXIT;
+        }
     }
 
     /* The basic registers are data only, and unknown registers
@@ -1615,11 +1631,13 @@ static void gen_mfpr(int ra, int regno)
     } else {
         tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
     }
+    return NO_EXIT;
 }
 
-static void gen_mtpr(int rb, int regno)
+static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
 {
     TCGv tmp;
+    int data;
 
     if (rb == 31) {
         tmp = tcg_const_i64(0);
@@ -1627,19 +1645,37 @@ static void gen_mtpr(int rb, int regno)
         tmp = cpu_ir[rb];
     }
 
-    /* These two register numbers perform a TLB cache flush.  Thankfully we
-       can only do this inside PALmode, which means that the current basic
-       block cannot be affected by the change in mappings.  */
-    if (regno == 255) {
+    switch (regno) {
+    case 255:
         /* TBIA */
         gen_helper_tbia();
-    } else if (regno == 254) {
+        break;
+
+    case 254:
         /* TBIS */
         gen_helper_tbis(tmp);
-    } else {
+        break;
+
+    case 253:
+        /* WAIT */
+        tmp = tcg_const_i64(1);
+        tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted));
+        return gen_excp(ctx, EXCP_HLT, 0);
+
+    case 252:
+        /* HALT */
+        gen_helper_halt(tmp);
+        return EXIT_PC_STALE;
+
+    case 251:
+        /* ALARM */
+        gen_helper_set_alarm(tmp);
+        break;
+
+    default:
         /* The basic registers are data only, and unknown registers
            are read-zero, write-ignore.  */
-        int data = cpu_pr_data(regno);
+        data = cpu_pr_data(regno);
         if (data != 0) {
             if (data & PR_BYTE) {
                 tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
@@ -1649,11 +1685,14 @@ static void gen_mtpr(int rb, int regno)
                 tcg_gen_st_i64(tmp, cpu_env, data);
             }
         }
+        break;
     }
 
     if (rb == 31) {
         tcg_temp_free(tmp);
     }
+
+    return NO_EXIT;
 }
 #endif /* !USER_ONLY*/
 
@@ -2721,8 +2760,16 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0xC000:
             /* RPCC */
-            if (ra != 31)
-                gen_helper_load_pcc(cpu_ir[ra]);
+            if (ra != 31) {
+                if (use_icount) {
+                    gen_io_start();
+                    gen_helper_load_pcc(cpu_ir[ra]);
+                    gen_io_end();
+                    ret = EXIT_PC_STALE;
+                } else {
+                    gen_helper_load_pcc(cpu_ir[ra]);
+                }
+            }
             break;
         case 0xE000:
             /* RC */
@@ -2747,8 +2794,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         /* HW_MFPR (PALcode) */
 #ifndef CONFIG_USER_ONLY
         if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            gen_mfpr(ra, insn & 0xffff);
-            break;
+            return gen_mfpr(ra, insn & 0xffff);
         }
 #endif
         goto invalid_opc;
@@ -3053,8 +3099,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
         /* HW_MTPR (PALcode) */
 #ifndef CONFIG_USER_ONLY
         if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
-            gen_mtpr(rb, insn & 0xffff);
-            break;
+            return gen_mtpr(ctx, rb, insn & 0xffff);
         }
 #endif
         goto invalid_opc;
index d3a3ba207f0d40c1df9a13118ce61a4e788ffed8..e2428eb7b2716564743efed40ad1b9fe5ebc4859 100644 (file)
@@ -298,7 +298,7 @@ void cpu_reset(CPUARMState *env)
         if (rom) {
             /* We should really use ldl_phys here, in case the guest
                modified flash and reset itself.  However images
-               loaded via -kenrel have not been copied yet, so load the
+               loaded via -kernel have not been copied yet, so load the
                values directly from there.  */
             env->regs[13] = ldl_p(rom);
             pc = ldl_p(rom + 4);
index ab9c9239d3a28478727cfbe54ec80ecc245e02af..1892b35ecc2db3fc09a8ea5baac2355013c44567 100644 (file)
@@ -84,6 +84,7 @@ void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
     int ret;
 
     saved_env = env;
+    env = env1;
     ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret)) {
         if (retaddr) {
index ae36489a9aa52578de068269224c97a200034601..a973f2e20cc54d35ebf226419bdb59db13d1c143 100644 (file)
 #define MSR_IA32_APICBASE_BSP           (1<<8)
 #define MSR_IA32_APICBASE_ENABLE        (1<<11)
 #define MSR_IA32_APICBASE_BASE          (0xfffff<<12)
+#define MSR_IA32_TSCDEADLINE            0x6e0
 
 #define MSR_MTRRcap                    0xfe
 #define MSR_MTRRcap_VCNT               8
@@ -687,6 +688,7 @@ typedef struct CPUX86State {
     uint64_t async_pf_en_msr;
 
     uint64_t tsc;
+    uint64_t tsc_deadline;
 
     uint64_t mcg_status;
 
@@ -947,7 +949,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);
 #define cpu_list_id x86_cpu_list
 #define cpudef_setup   x86_cpudef_setup
 
-#define CPU_SAVE_VERSION 12
+#define CPU_SAVE_VERSION 13
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
index b6eef047bfb37c6fbd22b647e59a3ed8fde71968..90a6ffba0204122e538a172d06b79eeec56d2325 100644 (file)
@@ -59,6 +59,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 
 static bool has_msr_star;
 static bool has_msr_hsave_pa;
+static bool has_msr_tsc_deadline;
 static bool has_msr_async_pf_en;
 static int lm_capable_kernel;
 
@@ -568,6 +569,10 @@ static int kvm_get_supported_msrs(KVMState *s)
                     has_msr_hsave_pa = true;
                     continue;
                 }
+                if (kvm_msr_list->indices[i] == MSR_IA32_TSCDEADLINE) {
+                    has_msr_tsc_deadline = true;
+                    continue;
+                }
             }
         }
 
@@ -881,6 +886,9 @@ static int kvm_put_msrs(CPUState *env, int level)
     if (has_msr_hsave_pa) {
         kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
     }
+    if (has_msr_tsc_deadline) {
+        kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSCDEADLINE, env->tsc_deadline);
+    }
 #ifdef TARGET_X86_64
     if (lm_capable_kernel) {
         kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar);
@@ -1127,6 +1135,9 @@ static int kvm_get_msrs(CPUState *env)
     if (has_msr_hsave_pa) {
         msrs[n++].index = MSR_VM_HSAVE_PA;
     }
+    if (has_msr_tsc_deadline) {
+        msrs[n++].index = MSR_IA32_TSCDEADLINE;
+    }
 
     if (!env->tsc_valid) {
         msrs[n++].index = MSR_IA32_TSC;
@@ -1195,6 +1206,9 @@ static int kvm_get_msrs(CPUState *env)
         case MSR_IA32_TSC:
             env->tsc = msrs[i].data;
             break;
+        case MSR_IA32_TSCDEADLINE:
+            env->tsc_deadline = msrs[i].data;
+            break;
         case MSR_VM_HSAVE_PA:
             env->vm_hsave = msrs[i].data;
             break;
index 9aca8e052381d1065ebd45054ba10233190642a2..25fa97de4a5670d42c6c399eb7cb191e3d908bf2 100644 (file)
@@ -410,6 +410,7 @@ static const VMStateDescription vmstate_cpu = {
         VMSTATE_UINT64_V(xcr0, CPUState, 12),
         VMSTATE_UINT64_V(xstate_bv, CPUState, 12),
         VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12),
+        VMSTATE_UINT64_V(tsc_deadline, CPUState, 13),
         VMSTATE_END_OF_LIST()
         /* The above list is not sorted /wrt version numbers, watch out! */
     },
index 014fd8de060194e148067dec218dd31dff2b23ce..fc0b444d81d7c75d15ce356ab375586bbdca32fd 100644 (file)
@@ -218,6 +218,7 @@ CPUState *cpu_lm32_init(const char *cpu_model)
 
     cpu_exec_init(env);
     cpu_reset(env);
+    qemu_init_vcpu(env);
 
     if (!tcg_initialized) {
         tcg_initialized = 1;
index b8d42e0b2c2e44fc57f865dff1889d36853b3074..3f77e308a6e842967b380c2f21f774db5555e350 100644 (file)
@@ -555,6 +555,8 @@ enum {
     /* Decrementer clock: RTC clock (POWER, 601) or bus clock                */
     POWERPC_FLAG_RTC_CLK  = 0x00010000,
     POWERPC_FLAG_BUS_CLK  = 0x00020000,
+    /* Has CFAR                                                              */
+    POWERPC_FLAG_CFAR     = 0x00040000,
 };
 
 /*****************************************************************************/
@@ -667,8 +669,8 @@ enum {
 #define MAS0_ATSEL_TLB     0
 #define MAS0_ATSEL_LRAT    MAS0_ATSEL
 
-#define MAS1_TSIZE_SHIFT   8
-#define MAS1_TSIZE_MASK    (0xf << MAS1_TSIZE_SHIFT)
+#define MAS1_TSIZE_SHIFT   7
+#define MAS1_TSIZE_MASK    (0x1f << MAS1_TSIZE_SHIFT)
 
 #define MAS1_TS_SHIFT      12
 #define MAS1_TS            (1 << MAS1_TS_SHIFT)
@@ -872,6 +874,10 @@ struct CPUPPCState {
     target_ulong ctr;
     /* condition register */
     uint32_t crf[8];
+#if defined(TARGET_PPC64)
+    /* CFAR */
+    target_ulong cfar;
+#endif
     /* XER */
     target_ulong xer;
     /* Reservation address */
@@ -934,6 +940,8 @@ struct CPUPPCState {
     ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed        */
     /* 403 dedicated access protection registers */
     target_ulong pb[4];
+    bool tlb_dirty;   /* Set to non-zero when modifying TLB                  */
+    bool kvm_sw_tlb;  /* non-zero if KVM SW TLB API is active                */
 #endif
 
     /* Other registers */
@@ -1010,8 +1018,35 @@ struct CPUPPCState {
 #if !defined(CONFIG_USER_ONLY)
     void *load_info;    /* Holds boot loading state.  */
 #endif
+
+    /* booke timers */
+
+    /* Specifies bit locations of the Time Base used to signal a fixed timer
+     * exception on a transition from 0 to 1. (watchdog or fixed-interval timer)
+     *
+     * 0 selects the least significant bit.
+     * 63 selects the most significant bit.
+     */
+    uint8_t fit_period[4];
+    uint8_t wdt_period[4];
 };
 
+#define SET_FIT_PERIOD(a_, b_, c_, d_)          \
+do {                                            \
+    env->fit_period[0] = (a_);                  \
+    env->fit_period[1] = (b_);                  \
+    env->fit_period[2] = (c_);                  \
+    env->fit_period[3] = (d_);                  \
+ } while (0)
+
+#define SET_WDT_PERIOD(a_, b_, c_, d_)          \
+do {                                            \
+    env->wdt_period[0] = (a_);                  \
+    env->wdt_period[1] = (b_);                  \
+    env->wdt_period[2] = (c_);                  \
+    env->wdt_period[3] = (d_);                  \
+ } while (0)
+
 #if !defined(CONFIG_USER_ONLY)
 /* Context used internally during MMU translations */
 typedef struct mmu_ctx_t mmu_ctx_t;
@@ -1202,6 +1237,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 #define SPR_601_UDECR         (0x006)
 #define SPR_LR                (0x008)
 #define SPR_CTR               (0x009)
+#define SPR_DSCR              (0x011)
 #define SPR_DSISR             (0x012)
 #define SPR_DAR               (0x013) /* DAE for PowerPC 601 */
 #define SPR_601_RTCU          (0x014)
@@ -1210,6 +1246,7 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 #define SPR_SDR1              (0x019)
 #define SPR_SRR0              (0x01A)
 #define SPR_SRR1              (0x01B)
+#define SPR_CFAR              (0x01C)
 #define SPR_AMR               (0x01D)
 #define SPR_BOOKE_PID         (0x030)
 #define SPR_BOOKE_DECAR       (0x036)
@@ -2043,4 +2080,6 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
     env->nip = tb->pc;
 }
 
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
+
 #endif /* !defined (__CPU_PPC_H__) */
index 96ea46494ad48598f9a2a324369d5dc8e5c90b6c..6339be3a75a6ceab48dc0053867e1f6e981a15a0 100644 (file)
@@ -1293,7 +1293,7 @@ target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
 {
     uint32_t tlbncfg;
     int tlbn = booke206_tlbm_to_tlbn(env, tlb);
-    target_phys_addr_t tlbm_size;
+    int tlbm_size;
 
     tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
 
@@ -1301,9 +1301,10 @@ target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
         tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
     } else {
         tlbm_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
+        tlbm_size <<= 1;
     }
 
-    return (1 << (tlbm_size << 1)) << 10;
+    return 1024ULL << tlbm_size;
 }
 
 /* TLB check function for MAS based SoftTLBs */
@@ -1465,6 +1466,94 @@ found_tlb:
     return ret;
 }
 
+static const char *book3e_tsize_to_str[32] = {
+    "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
+    "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
+    "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
+    "1T", "2T"
+};
+
+static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
+                                     CPUState *env, int tlbn, int offset,
+                                     int tlbsize)
+{
+    ppcmas_tlb_t *entry;
+    int i;
+
+    cpu_fprintf(f, "\nTLB%d:\n", tlbn);
+    cpu_fprintf(f, "Effective          Physical           Size TID   TS SRWX URWX WIMGE U0123\n");
+
+    entry = &env->tlb.tlbm[offset];
+    for (i = 0; i < tlbsize; i++, entry++) {
+        target_phys_addr_t ea, pa, size;
+        int tsize;
+
+        if (!(entry->mas1 & MAS1_VALID)) {
+            continue;
+        }
+
+        tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
+        size = 1024ULL << tsize;
+        ea = entry->mas2 & ~(size - 1);
+        pa = entry->mas7_3 & ~(size - 1);
+
+        cpu_fprintf(f, "0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
+                    (uint64_t)ea, (uint64_t)pa,
+                    book3e_tsize_to_str[tsize],
+                    (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
+                    (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
+                    entry->mas7_3 & MAS3_SR ? 'R' : '-',
+                    entry->mas7_3 & MAS3_SW ? 'W' : '-',
+                    entry->mas7_3 & MAS3_SX ? 'X' : '-',
+                    entry->mas7_3 & MAS3_UR ? 'R' : '-',
+                    entry->mas7_3 & MAS3_UW ? 'W' : '-',
+                    entry->mas7_3 & MAS3_UX ? 'X' : '-',
+                    entry->mas2 & MAS2_W ? 'W' : '-',
+                    entry->mas2 & MAS2_I ? 'I' : '-',
+                    entry->mas2 & MAS2_M ? 'M' : '-',
+                    entry->mas2 & MAS2_G ? 'G' : '-',
+                    entry->mas2 & MAS2_E ? 'E' : '-',
+                    entry->mas7_3 & MAS3_U0 ? '0' : '-',
+                    entry->mas7_3 & MAS3_U1 ? '1' : '-',
+                    entry->mas7_3 & MAS3_U2 ? '2' : '-',
+                    entry->mas7_3 & MAS3_U3 ? '3' : '-');
+    }
+}
+
+static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
+                                 CPUState *env)
+{
+    int offset = 0;
+    int i;
+
+    if (kvm_enabled() && !env->kvm_sw_tlb) {
+        cpu_fprintf(f, "Cannot access KVM TLB\n");
+        return;
+    }
+
+    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+        int size = booke206_tlb_size(env, i);
+
+        if (size == 0) {
+            continue;
+        }
+
+        mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
+        offset += size;
+    }
+}
+
+void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
+{
+    switch (env->mmu_model) {
+    case POWERPC_MMU_BOOKE206:
+        mmubooke206_dump_mmu(f, cpu_fprintf, env);
+        break;
+    default:
+        cpu_fprintf(f, "%s: unimplemented\n", __func__);
+    }
+}
+
 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
                                  target_ulong eaddr, int rw)
 {
index 21f35af762b1500bea12b35c469b55806533ad50..75832d83b83c75fbc59654b9fa9513777865648b 100644 (file)
@@ -14,6 +14,7 @@
  *
  */
 
+#include <dirent.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include "cpu.h"
 #include "device_tree.h"
 
+#include "hw/sysbus.h"
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
 //#define DEBUG_KVM
 
 #ifdef DEBUG_KVM
@@ -38,6 +43,8 @@
     do { } while (0)
 #endif
 
+#define PROC_DEVTREE_CPU      "/proc/device-tree/cpus/"
+
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
@@ -105,6 +112,52 @@ static int kvm_arch_sync_sregs(CPUState *cenv)
     return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
 }
 
+/* Set up a shared TLB array with KVM */
+static int kvm_booke206_tlb_init(CPUState *env)
+{
+    struct kvm_book3e_206_tlb_params params = {};
+    struct kvm_config_tlb cfg = {};
+    struct kvm_enable_cap encap = {};
+    unsigned int entries = 0;
+    int ret, i;
+
+    if (!kvm_enabled() ||
+        !kvm_check_extension(env->kvm_state, KVM_CAP_SW_TLB)) {
+        return 0;
+    }
+
+    assert(ARRAY_SIZE(params.tlb_sizes) == BOOKE206_MAX_TLBN);
+
+    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+        params.tlb_sizes[i] = booke206_tlb_size(env, i);
+        params.tlb_ways[i] = booke206_tlb_ways(env, i);
+        entries += params.tlb_sizes[i];
+    }
+
+    assert(entries == env->nb_tlb);
+    assert(sizeof(struct kvm_book3e_206_tlb_entry) == sizeof(ppcmas_tlb_t));
+
+    env->tlb_dirty = true;
+
+    cfg.array = (uintptr_t)env->tlb.tlbm;
+    cfg.array_len = sizeof(ppcmas_tlb_t) * entries;
+    cfg.params = (uintptr_t)&params;
+    cfg.mmu_type = KVM_MMU_FSL_BOOKE_NOHV;
+
+    encap.cap = KVM_CAP_SW_TLB;
+    encap.args[0] = (uintptr_t)&cfg;
+
+    ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &encap);
+    if (ret < 0) {
+        fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n",
+                __func__, strerror(-ret));
+        return ret;
+    }
+
+    env->kvm_sw_tlb = true;
+    return 0;
+}
+
 int kvm_arch_init_vcpu(CPUState *cenv)
 {
     int ret;
@@ -116,6 +169,15 @@ int kvm_arch_init_vcpu(CPUState *cenv)
 
     idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv);
 
+    /* Some targets support access to KVM's guest TLB. */
+    switch (cenv->mmu_model) {
+    case POWERPC_MMU_BOOKE206:
+        ret = kvm_booke206_tlb_init(cenv);
+        break;
+    default:
+        break;
+    }
+
     return ret;
 }
 
@@ -123,6 +185,31 @@ void kvm_arch_reset_vcpu(CPUState *env)
 {
 }
 
+static void kvm_sw_tlb_put(CPUState *env)
+{
+    struct kvm_dirty_tlb dirty_tlb;
+    unsigned char *bitmap;
+    int ret;
+
+    if (!env->kvm_sw_tlb) {
+        return;
+    }
+
+    bitmap = g_malloc((env->nb_tlb + 7) / 8);
+    memset(bitmap, 0xFF, (env->nb_tlb + 7) / 8);
+
+    dirty_tlb.bitmap = (uintptr_t)bitmap;
+    dirty_tlb.num_dirty = env->nb_tlb;
+
+    ret = kvm_vcpu_ioctl(env, KVM_DIRTY_TLB, &dirty_tlb);
+    if (ret) {
+        fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n",
+                __func__, strerror(-ret));
+    }
+
+    g_free(bitmap);
+}
+
 int kvm_arch_put_registers(CPUState *env, int level)
 {
     struct kvm_regs regs;
@@ -160,6 +247,11 @@ int kvm_arch_put_registers(CPUState *env, int level)
     if (ret < 0)
         return ret;
 
+    if (env->tlb_dirty) {
+        kvm_sw_tlb_put(env);
+        env->tlb_dirty = false;
+    }
+
     return ret;
 }
 
@@ -452,6 +544,14 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
         dprintf("handle halt\n");
         ret = kvmppc_handle_halt(env);
         break;
+#ifdef CONFIG_PSERIES
+    case KVM_EXIT_PAPR_HCALL:
+        dprintf("handle PAPR hypercall\n");
+        run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr,
+                                              run->papr_hcall.args);
+        ret = 1;
+        break;
+#endif
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
@@ -509,6 +609,70 @@ uint32_t kvmppc_get_tbfreq(void)
     return retval;
 }
 
+/* Try to find a device tree node for a CPU with clock-frequency property */
+static int kvmppc_find_cpu_dt(char *buf, int buf_len)
+{
+    struct dirent *dirp;
+    DIR *dp;
+
+    if ((dp = opendir(PROC_DEVTREE_CPU)) == NULL) {
+        printf("Can't open directory " PROC_DEVTREE_CPU "\n");
+        return -1;
+    }
+
+    buf[0] = '\0';
+    while ((dirp = readdir(dp)) != NULL) {
+        FILE *f;
+        snprintf(buf, buf_len, "%s%s/clock-frequency", PROC_DEVTREE_CPU,
+                 dirp->d_name);
+        f = fopen(buf, "r");
+        if (f) {
+            snprintf(buf, buf_len, "%s%s", PROC_DEVTREE_CPU, dirp->d_name);
+            fclose(f);
+            break;
+        }
+        buf[0] = '\0';
+    }
+    closedir(dp);
+    if (buf[0] == '\0') {
+        printf("Unknown host!\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+uint64_t kvmppc_get_clockfreq(void)
+{
+    char buf[512];
+    uint32_t tb[2];
+    FILE *f;
+    int len;
+
+    if (kvmppc_find_cpu_dt(buf, sizeof(buf))) {
+        return 0;
+    }
+
+    strncat(buf, "/clock-frequency", sizeof(buf) - strlen(buf));
+
+    f = fopen(buf, "rb");
+    if (!f) {
+        return -1;
+    }
+
+    len = fread(tb, sizeof(tb[0]), 2, f);
+    fclose(f);
+    switch (len) {
+    case 1:
+        /* freq is only a single cell */
+        return tb[0];
+    case 2:
+        return *(uint64_t*)tb;
+    }
+
+    return 0;
+}
+
 int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
 {
     uint32_t *hc = (uint32_t*)buf;
@@ -539,6 +703,53 @@ int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
     return 0;
 }
 
+void kvmppc_set_papr(CPUState *env)
+{
+    struct kvm_enable_cap cap = {};
+    struct kvm_one_reg reg = {};
+    struct kvm_sregs sregs = {};
+    int ret;
+
+    cap.cap = KVM_CAP_PPC_PAPR;
+    ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
+
+    if (ret) {
+        goto fail;
+    }
+
+    /*
+     * XXX We set HIOR here. It really should be a qdev property of
+     *     the CPU node, but we don't have CPUs converted to qdev yet.
+     *
+     *     Once we have qdev CPUs, move HIOR to a qdev property and
+     *     remove this chunk.
+     */
+    reg.id = KVM_ONE_REG_PPC_HIOR;
+    reg.u.reg64 = env->spr[SPR_HIOR];
+    ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &reg);
+    if (ret) {
+        goto fail;
+    }
+
+    /* Set SDR1 so kernel space finds the HTAB */
+    ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
+    if (ret) {
+        goto fail;
+    }
+
+    sregs.u.s.sdr1 = env->spr[SPR_SDR1];
+
+    ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
+    if (ret) {
+        goto fail;
+    }
+
+    return;
+
+fail:
+    cpu_abort(env, "This KVM version does not support PAPR\n");
+}
+
 bool kvm_arch_stop_on_emulation_error(CPUState *env)
 {
     return true;
index c031fcb75a7ce837b662be41d61cc0fe123de571..24fc6bce3b86c34b74649199c95b6bcc7e1e2007 100644 (file)
 static QEMUTimer *kvmppc_timer;
 static unsigned int kvmppc_timer_rate;
 
-#ifdef CONFIG_FDT
-int kvmppc_read_host_property(const char *node_path, const char *prop,
-                                     void *val, size_t len)
-{
-    char *path;
-    FILE *f;
-    int ret = 0;
-    int pathlen;
-
-    pathlen = snprintf(NULL, 0, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop)
-              + 1;
-    path = g_malloc(pathlen);
-
-    snprintf(path, pathlen, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop);
-
-    f = fopen(path, "rb");
-    if (f == NULL) {
-        ret = errno;
-        goto free;
-    }
-
-    len = fread(val, len, 1, f);
-    if (len != 1) {
-        ret = ferror(f);
-        goto close;
-    }
-
-close:
-    fclose(f);
-free:
-    free(path);
-    return ret;
-}
-
-static int kvmppc_copy_host_cell(void *fdt, const char *node, const char *prop)
-{
-    uint32_t cell;
-    int ret;
-
-    ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
-    if (ret < 0) {
-        fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
-        goto out;
-    }
-
-    ret = qemu_devtree_setprop_cell(fdt, node, prop, cell);
-    if (ret < 0) {
-        fprintf(stderr, "couldn't set guest %s/%s\n", node, prop);
-        goto out;
-    }
-
-out:
-    return ret;
-}
-
-void kvmppc_fdt_update(void *fdt)
-{
-    /* Copy data from the host device tree into the guest. Since the guest can
-     * directly access the timebase without host involvement, we must expose
-     * the correct frequencies. */
-    kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "clock-frequency");
-    kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "timebase-frequency");
-}
-#endif
-
 static void kvmppc_timer_hack(void *opaque)
 {
     qemu_notify_event();
index 45a1373b28130aa1f15ee256d862b82a0c2aa985..c484e60bcb686873292a104f43497dc43299ca58 100644 (file)
 #define __KVM_PPC_H__
 
 void kvmppc_init(void);
-void kvmppc_fdt_update(void *fdt);
-#ifndef CONFIG_KVM
-static inline int kvmppc_read_host_property(const char *node_path, const char *prop,
-                                            void *val, size_t len)
-{
-    assert(0);
-    return -ENOSYS;
-}
-#else
-int kvmppc_read_host_property(const char *node_path, const char *prop,
-                                     void *val, size_t len);
-#endif
+
+#ifdef CONFIG_KVM
 
 uint32_t kvmppc_get_tbfreq(void);
+uint64_t kvmppc_get_clockfreq(void);
 int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
 int kvmppc_set_interrupt(CPUState *env, int irq, int level);
+void kvmppc_set_papr(CPUState *env);
+
+#else
+
+static inline uint32_t kvmppc_get_tbfreq(void)
+{
+    return 0;
+}
+
+static inline uint64_t kvmppc_get_clockfreq(void)
+{
+    return 0;
+}
+
+static inline int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
+{
+    return -1;
+}
+
+static inline int kvmppc_set_interrupt(CPUState *env, int irq, int level)
+{
+    return -1;
+}
+
+static inline void kvmppc_set_papr(CPUState *env)
+{
+}
+
+#endif
 
 #ifndef CONFIG_KVM
 #define kvmppc_eieio() do { } while (0)
index 42774606923eb8f4cce17d8277342f8179d12dde..1e362fc2385faeca53d0c1de37ccd7a7379202da 100644 (file)
@@ -69,6 +69,9 @@ static TCGv cpu_nip;
 static TCGv cpu_msr;
 static TCGv cpu_ctr;
 static TCGv cpu_lr;
+#if defined(TARGET_PPC64)
+static TCGv cpu_cfar;
+#endif
 static TCGv cpu_xer;
 static TCGv cpu_reserve;
 static TCGv_i32 cpu_fpscr;
@@ -154,6 +157,11 @@ void ppc_translate_init(void)
     cpu_lr = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, lr), "lr");
 
+#if defined(TARGET_PPC64)
+    cpu_cfar = tcg_global_mem_new(TCG_AREG0,
+                                  offsetof(CPUState, cfar), "cfar");
+#endif
+
     cpu_xer = tcg_global_mem_new(TCG_AREG0,
                                  offsetof(CPUState, xer), "xer");
 
@@ -187,6 +195,7 @@ typedef struct DisasContext {
     int le_mode;
 #if defined(TARGET_PPC64)
     int sf_mode;
+    int has_cfar;
 #endif
     int fpu_enabled;
     int altivec_enabled;
@@ -3345,6 +3354,14 @@ static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
 /* stfiwx */
 GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
 
+static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
+{
+#if defined(TARGET_PPC64)
+    if (ctx->has_cfar)
+        tcg_gen_movi_tl(cpu_cfar, nip);
+#endif
+}
+
 /***                                Branch                                 ***/
 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 {
@@ -3407,6 +3424,7 @@ static void gen_b(DisasContext *ctx)
         target = li;
     if (LK(ctx->opcode))
         gen_setlr(ctx, ctx->nip);
+    gen_update_cfar(ctx, ctx->nip);
     gen_goto_tb(ctx, 0, target);
 }
 
@@ -3469,6 +3487,7 @@ static inline void gen_bcond(DisasContext *ctx, int type)
         }
         tcg_temp_free_i32(temp);
     }
+    gen_update_cfar(ctx, ctx->nip);
     if (type == BCOND_IM) {
         target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
         if (likely(AA(ctx->opcode) == 0)) {
@@ -3580,6 +3599,7 @@ static void gen_rfi(DisasContext *ctx)
         gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
         return;
     }
+    gen_update_cfar(ctx, ctx->nip);
     gen_helper_rfi();
     gen_sync_exception(ctx);
 #endif
@@ -3596,6 +3616,7 @@ static void gen_rfid(DisasContext *ctx)
         gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
         return;
     }
+    gen_update_cfar(ctx, ctx->nip);
     gen_helper_rfid();
     gen_sync_exception(ctx);
 #endif
@@ -9263,6 +9284,12 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
          */
     }
 
+#if defined(TARGET_PPC64)
+    if (env->flags & POWERPC_FLAG_CFAR) {
+        cpu_fprintf(f, " CFAR " TARGET_FMT_lx"\n", env->cfar);
+    }
+#endif
+
     switch (env->mmu_model) {
     case POWERPC_MMU_32B:
     case POWERPC_MMU_601:
@@ -9371,6 +9398,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
     ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;
 #if defined(TARGET_PPC64)
     ctx.sf_mode = msr_sf;
+    ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
 #endif
     ctx.fpu_enabled = msr_fp;
     if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
index 9ea193dcf69e2ab20516f48bfb5f3951aec9447b..ca0d8525c8d70424a7a766591ce80b06124d824f 100644 (file)
@@ -129,6 +129,19 @@ static void spr_write_lr (void *opaque, int sprn, int gprn)
     tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
 }
 
+/* CFAR */
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+static void spr_read_cfar (void *opaque, int gprn, int sprn)
+{
+    tcg_gen_mov_tl(cpu_gpr[gprn], cpu_cfar);
+}
+
+static void spr_write_cfar (void *opaque, int sprn, int gprn)
+{
+    tcg_gen_mov_tl(cpu_cfar, cpu_gpr[gprn]);
+}
+#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
+
 /* CTR */
 static void spr_read_ctr (void *opaque, int gprn, int sprn)
 {
@@ -3253,6 +3266,9 @@ static void init_proc_401 (CPUPPCState *env)
     env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
 /* PowerPC 401x2                                                             */
@@ -3291,6 +3307,9 @@ static void init_proc_401x2 (CPUPPCState *env)
     env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
 /* PowerPC 401x3                                                             */
@@ -3324,6 +3343,9 @@ static void init_proc_401x3 (CPUPPCState *env)
     env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
 /* IOP480                                                                    */
@@ -3362,6 +3384,9 @@ static void init_proc_IOP480 (CPUPPCState *env)
     env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(8, 12, 16, 20);
+    SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
 /* PowerPC 403                                                               */
@@ -3392,6 +3417,9 @@ static void init_proc_403 (CPUPPCState *env)
     env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(8, 12, 16, 20);
+    SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
 /* PowerPC 403 GCX                                                           */
@@ -3442,6 +3470,9 @@ static void init_proc_403GCX (CPUPPCState *env)
     env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(8, 12, 16, 20);
+    SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
 /* PowerPC 405                                                               */
@@ -3491,6 +3522,9 @@ static void init_proc_405 (CPUPPCState *env)
     env->icache_line_size = 32;
     /* Allocate hardware IRQ controller */
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(8, 12, 16, 20);
+    SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
 /* PowerPC 440 EP                                                            */
@@ -3573,6 +3607,9 @@ static void init_proc_440EP (CPUPPCState *env)
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
     /* XXX: TODO: allocate internal IRQ controller */
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
 /* PowerPC 440 GP                                                            */
@@ -3637,6 +3674,9 @@ static void init_proc_440GP (CPUPPCState *env)
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
     /* XXX: TODO: allocate internal IRQ controller */
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
 /* PowerPC 440x4                                                             */
@@ -3701,6 +3741,9 @@ static void init_proc_440x4 (CPUPPCState *env)
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
     /* XXX: TODO: allocate internal IRQ controller */
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
 /* PowerPC 440x5                                                             */
@@ -3782,6 +3825,9 @@ static void init_proc_440x5 (CPUPPCState *env)
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
     ppc40x_irq_init(env);
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
 /* PowerPC 460 (guessed)                                                     */
@@ -3870,6 +3916,9 @@ static void init_proc_460 (CPUPPCState *env)
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
     /* XXX: TODO: allocate internal IRQ controller */
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
 /* PowerPC 460F (guessed)                                                    */
@@ -3961,6 +4010,9 @@ static void init_proc_460F (CPUPPCState *env)
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
     /* XXX: TODO: allocate internal IRQ controller */
+
+    SET_FIT_PERIOD(12, 16, 20, 24);
+    SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
 /* Freescale 5xx cores (aka RCPU) */
@@ -6489,7 +6541,7 @@ static void init_proc_970MP (CPUPPCState *env)
 #define POWERPC_BFDM_POWER7   (bfd_mach_ppc64)
 #define POWERPC_FLAG_POWER7   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
+                              POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR)
 #define check_pow_POWER7    check_pow_nocheck
 
 static void init_proc_POWER7 (CPUPPCState *env)
@@ -6508,6 +6560,14 @@ static void init_proc_POWER7 (CPUPPCState *env)
                  &spr_read_purr, SPR_NOACCESS,
                  &spr_read_purr, SPR_NOACCESS,
                  0x00000000);
+    spr_register(env, SPR_CFAR, "SPR_CFAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_cfar, &spr_write_cfar,
+                 0x00000000);
+    spr_register(env, SPR_DSCR, "SPR_DSCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
 #endif /* !CONFIG_USER_ONLY */
     /* Memory management */
     /* XXX : not implemented */
@@ -9679,8 +9739,7 @@ static int gdb_get_float_reg(CPUState *env, uint8_t *mem_buf, int n)
         return 8;
     }
     if (n == 32) {
-        /* FPSCR not implemented  */
-        memset(mem_buf, 0, 4);
+        stl_p(mem_buf, env->fpscr);
         return 4;
     }
     return 0;
index 3803ab6bfa49a2a79050b359791e026fc2aef76a..bb22b9abece03c120717d5008a0d3a6c20e6460c 100644 (file)
@@ -847,25 +847,6 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
                    tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, reg, arg));
 }
 
-static inline void tcg_out_addi(TCGContext *s, TCGArg reg, tcg_target_long val)
-{
-    if (val == ((int32_t)val << 10) >> 10) {
-        tcg_out_bundle(s, MmI,
-                       tcg_opc_a5(TCG_REG_P0, OPC_ADDL_A5,
-                                  TCG_REG_R2, val, TCG_REG_R0),
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, reg,
-                                   reg, TCG_REG_R2));
-    } else {
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, val);
-        tcg_out_bundle(s, mmI,
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
-                       tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, reg,
-                                   reg, TCG_REG_R2));
-    }
-}
-
 static void tcg_out_br(TCGContext *s, int label_index)
 {
     TCGLabel *l = &s->labels[label_index];
index b58df719a64f031afc85c0fc18491101adf5c934..9317fe88ef2d08f006de907dd4f744a487b570cc 100644 (file)
@@ -2322,8 +2322,3 @@ static void tcg_target_qemu_prologue(TCGContext *s)
     /* br %r14 (return) */
     tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_R14);
 }
-
-static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
-{
-    tcg_abort();
-}
index b7ddf14bd883f75693d729b9ad505380b9470a9c..63d8c8ed750ee63bcc60f926ef84d448efcbcc64 100644 (file)
@@ -56,6 +56,7 @@ virtio_console_chr_read(unsigned int port, int size) "port %u, size %d"
 virtio_console_chr_event(unsigned int port, int event) "port %u, event %d"
 
 # block.c
+bdrv_open_common(void *bs, const char *filename, int flags, const char *format_name) "bs %p filename \"%s\" flags %#x format_name \"%s\""
 multiwrite_cb(void *mcb, int ret) "mcb %p ret %d"
 bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d"
 bdrv_aio_multiwrite_earlyfail(void *mcb) "mcb %p"
@@ -66,7 +67,7 @@ bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs
 bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d"
 bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
-bdrv_co_io(int is_write, void *acb) "is_write %d acb %p"
+bdrv_co_io_em(void *bs, int64_t sector_num, int nb_sectors, int is_write, void *acb) "bs %p sector_num %"PRId64" nb_sectors %d is_write %d acb %p"
 
 # hw/virtio-blk.c
 virtio_blk_req_complete(void *req, int status) "req %p status %d"
@@ -444,8 +445,8 @@ milkymist_tmu2_pulse_irq(void) "Pulse IRQ"
 # hw/milkymist-uart.c
 milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
 milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
-milkymist_uart_pulse_irq_rx(void) "Pulse IRQ RX"
-milkymist_uart_pulse_irq_tx(void) "Pulse IRQ TX"
+milkymist_uart_raise_irq(void) "Raise IRQ"
+milkymist_uart_lower_irq(void) "Lower IRQ"
 
 # hw/milkymist-vgafb.c
 milkymist_vgafb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
@@ -533,3 +534,7 @@ esp_mem_writeb_cmd_sel(uint32_t val) "Select without ATN (%2.2x)"
 esp_mem_writeb_cmd_selatn(uint32_t val) "Select with ATN (%2.2x)"
 esp_mem_writeb_cmd_selatns(uint32_t val) "Select with ATN & stop (%2.2x)"
 esp_mem_writeb_cmd_ensel(uint32_t val) "Enable selection (%2.2x)"
+
+# monitor.c
+handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
+monitor_protocol_emitter(void *mon) "mon %p"
This page took 0.356209 seconds and 4 git commands to generate.