]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
authorPeter Maydell <peter.maydell@linaro.org>
Mon, 9 Jun 2014 10:54:22 +0000 (11:54 +0100)
committerPeter Maydell <peter.maydell@linaro.org>
Mon, 9 Jun 2014 10:54:22 +0000 (11:54 +0100)
Block pull request

# gpg: Signature made Fri 06 Jun 2014 17:08:50 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/block-pull-request: (42 commits)
  qapi: Extract qapi/block.json definitions
  qapi: Extract qapi/block-core.json definitions
  qapi: create two block related json modules
  qapi: Extract qapi/common.json definitions
  sheepdog: reload only header in a case of live snapshot
  sheepdog: fix vdi object update after live snapshot
  rbd: Fix leaks in rbd_start_aio() error path
  qemu-img: Document check exit codes
  block: fix wrong order in live block migration setup
  blockdev: acquire AioContext in block_set_io_throttle
  throttle: add detach/attach test case
  throttle: add throttle_detach/attach_aio_context()
  dataplane: Support VIRTIO_BLK_T_SCSI_CMD
  virtio-blk: Factor out virtio_blk_handle_scsi_req from virtio_blk_handle_scsi
  virtio-blk: Allow config-wce in dataplane
  block: Move declaration of bdrv_get_aio_context to block.h
  raw-posix: drop raw_get_aio_fd() since it is no longer used
  dataplane: implement async flush
  dataplane: delete IOQueue since it is no longer used
  dataplane: use the QEMU block layer for I/O
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
150 files changed:
bsd-user/main.c
bsd-user/qemu.h
cputlb.c
docs/multiseat.txt
docs/virtio-balloon-stats.txt
hw/9pfs/virtio-9p-device.c
hw/arm/nseries.c
hw/block/virtio-blk.c
hw/char/serial-pci.c
hw/char/xilinx_uartlite.c
hw/core/qdev-properties-system.c
hw/core/qdev-properties.c
hw/display/cg3.c
hw/display/omap_lcd_template.h
hw/display/sm501_template.h
hw/display/tcx.c
hw/display/vga_template.h
hw/i386/kvm/clock.c
hw/i386/smbios.c
hw/intc/xilinx_intc.c
hw/mips/mips_fulong2e.c
hw/mips/mips_malta.c
hw/net/xilinx_ethlite.c
hw/pci-host/apb.c
hw/pci-host/q35.c
hw/pci/pcie_host.c
hw/scsi/vhost-scsi.c
hw/scsi/virtio-scsi.c
hw/sparc/sun4m.c
hw/timer/xilinx_timer.c
hw/virtio/virtio-balloon.c
include/exec/cpu-all.h
include/exec/cpu_ldst.h [new file with mode: 0644]
include/exec/cpu_ldst_template.h [new file with mode: 0644]
include/exec/exec-all.h
include/exec/softmmu_exec.h [deleted file]
include/exec/softmmu_header.h [deleted file]
include/exec/softmmu_template.h [deleted file]
include/hw/i386/pc.h
include/hw/i386/smbios.h
include/hw/pci/pcie_host.h
include/hw/qdev-core.h
include/hw/qdev-properties.h
include/qom/cpu.h
include/ui/input.h
kvm-all.c
linux-user/main.c
linux-user/qemu.h
monitor.c
qemu-options.hx
qga/commands-win32.c
scripts/kvm/kvm_stat
slirp/arp_table.c
slirp/slirp.c
softmmu_template.h [new file with mode: 0644]
target-alpha/cpu-qom.h
target-alpha/cpu.c
target-alpha/cpu.h
target-alpha/mem_helper.c
target-alpha/translate.c
target-arm/arm_ldst.h [new file with mode: 0644]
target-arm/cpu.h
target-arm/helper.c
target-arm/op_helper.c
target-arm/translate-a64.c
target-arm/translate.c
target-cris/helper.c
target-cris/op_helper.c
target-cris/translate.c
target-cris/translate_v10.c
target-i386/cpu-qom.h
target-i386/cpu.c
target-i386/cpu.h
target-i386/fpu_helper.c
target-i386/gdbstub.c
target-i386/helper.c
target-i386/kvm.c
target-i386/machine.c
target-i386/mem_helper.c
target-i386/misc_helper.c
target-i386/seg_helper.c
target-i386/smm_helper.c
target-i386/svm_helper.c
target-i386/translate.c
target-lm32/op_helper.c
target-lm32/translate.c
target-m68k/op_helper.c
target-m68k/translate.c
target-microblaze/op_helper.c
target-microblaze/translate.c
target-mips/cpu-qom.h
target-mips/cpu.c
target-mips/cpu.h
target-mips/op_helper.c
target-mips/translate.c
target-moxie/helper.c
target-moxie/translate.c
target-openrisc/mmu_helper.c
target-openrisc/translate.c
target-ppc/excp_helper.c
target-ppc/mem_helper.c
target-ppc/mmu_helper.c
target-ppc/translate.c
target-s390x/fpu_helper.c
target-s390x/helper.c
target-s390x/mem_helper.c
target-s390x/misc_helper.c
target-s390x/translate.c
target-sh4/op_helper.c
target-sh4/translate.c
target-sparc/cpu-qom.h
target-sparc/cpu.c
target-sparc/cpu.h
target-sparc/ldst_helper.c
target-sparc/translate.c
target-unicore32/op_helper.c
target-unicore32/translate.c
target-xtensa/cpu-qom.h
target-xtensa/cpu.c
target-xtensa/cpu.h
target-xtensa/op_helper.c
target-xtensa/translate.c
tcg/aarch64/tcg-target.h
tcg/arm/tcg-target.h
tcg/i386/tcg-target.c
tcg/i386/tcg-target.h
tcg/ia64/tcg-target.h
tcg/mips/tcg-target.h
tcg/optimize.c
tcg/ppc/tcg-target.h
tcg/ppc64/tcg-target.h
tcg/s390/tcg-target.h
tcg/sparc/tcg-target.h
tcg/tcg-op.h
tcg/tcg-opc.h
tcg/tcg.c
tcg/tcg.h
tcg/tci/tcg-target.c
tcg/tci/tcg-target.h
tci.c
tests/Makefile
tests/acpi-test.c [deleted file]
tests/bios-tables-test.c [new file with mode: 0644]
tests/test-qdev-global-props.c
ui/curses.c
ui/input-legacy.c
ui/input.c
ui/vnc.c
user-exec.c
vl.c

index 4ba61da8961a2d7b754899b9b7f05a86c464645a..0e8c26c137c7aff85f4c386e748de3fa411e691a 100644 (file)
@@ -1004,7 +1004,7 @@ int main(int argc, char **argv)
 
 #if defined(TARGET_I386)
     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
-    env->hflags |= HF_PE_MASK;
+    env->hflags |= HF_PE_MASK | HF_CPL_MASK;
     if (env->features[FEAT_1_EDX] & CPUID_SSE) {
         env->cr[4] |= CR4_OSFXSR_MASK;
         env->hflags |= HF_OSFXSR_MASK;
index ddc74ed0d725b791eba066f2ae2b46e5a3cf8442..9d90668ddda38324091b3ef3a12eaf1defeeafde 100644 (file)
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #include "cpu.h"
+#include "exec/cpu_ldst.h"
 
 #undef DEBUG_REMAP
 #ifdef DEBUG_REMAP
index 7bd3573025a247f1de8ecf9a234d0fdd1905aee9..afd3705ff38f07bc3d3cb8fd758dde8614b53505 100644 (file)
--- a/cputlb.c
+++ b/cputlb.c
 #include "exec/exec-all.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/cputlb.h"
 
 #include "exec/memory-internal.h"
 #include "exec/ram_addr.h"
+#include "tcg/tcg.h"
 
 //#define DEBUG_TLB
 //#define DEBUG_TLB_CHECK
@@ -330,21 +332,36 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
     return qemu_ram_addr_from_host_nofail(p);
 }
 
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+#undef MMUSUFFIX
+
 #define MMUSUFFIX _cmmu
-#undef GETPC
-#define GETPC() ((uintptr_t)0)
+#undef GETPC_ADJ
+#define GETPC_ADJ 0
+#undef GETRA
+#define GETRA() ((uintptr_t)0)
 #define SOFTMMU_CODE_ACCESS
 
 #define SHIFT 0
-#include "exec/softmmu_template.h"
+#include "softmmu_template.h"
 
 #define SHIFT 1
-#include "exec/softmmu_template.h"
+#include "softmmu_template.h"
 
 #define SHIFT 2
-#include "exec/softmmu_template.h"
+#include "softmmu_template.h"
 
 #define SHIFT 3
-#include "exec/softmmu_template.h"
-
-#undef env
+#include "softmmu_template.h"
index a6c71dd74f4bf7fbdfe6801689f1a77d57e75ff1..67151e084946fd257e024f19cc5975356384e4a0 100644 (file)
@@ -6,16 +6,20 @@ host side
 ---------
 
 First you must compile qemu with a user interface supporting
-multihead/multiseat and input event routing.  Right now this list is
-pretty short: sdl2.
+multihead/multiseat and input event routing.  Right now this
+list includes sdl2 and gtk (both 2+3):
 
   ./configure --enable-sdl --with-sdlabi=2.0
 
+or
+
+  ./configure --enable-gtk
+
 
 Next put together the qemu command line:
 
 qemu   -enable-kvm -usb $memory $disk $whatever \
-       -display sdl \
+       -display [ sdl | gtk ] \
        -vga std \
        -device usb-tablet
 
@@ -37,6 +41,20 @@ The "display=video2" sets up the input routing.  Any input coming from
 the window which belongs to the video.2 display adapter will be routed
 to these input devices.
 
+The sdl2 ui will start up with two windows, one for each display
+device.  The gtk ui will start with a single window and each display
+in a separate tab.  You can either simply switch tabs to switch heads,
+or use the "View / Detach tab" menu item to move one of the displays
+to its own window so you can see both display devices side-by-side.
+
+Note on spice: Spice handles multihead just fine.  But it can't do
+multiseat.  For tablet events the event source is sent to the spice
+agent.  But qemu can't figure it, so it can't do input routing.
+Fixing this needs a new or extended input interface between
+libspice-server and qemu.  For keyboard events it is even worse:  The
+event source isn't included in the spice protocol, so the wire
+protocol must be extended to support this.
+
 
 guest side
 ----------
@@ -46,29 +64,37 @@ You need a pretty recent linux guest.  systemd with loginctl.  kernel
 fully updated for the new kernel though, i.e. the live iso doesn't cut
 it.
 
-Now we'll have to configure the guest.  Boot and login.  By default
-all devices belong to seat0.  You can use "loginctl seat-status seat0"
-to list them all (and to get the sysfs paths for cut+paste).  Now
-we'll go assign all pci devices connected the pci bridge in slot 12 to
-a new head:
-
-loginctl attach seat-qemu \
-        /sys/devices/pci0000:00/0000:00:12.0/0000:01:02.0/drm/card1
-loginctl attach seat-qemu \
-        /sys/devices/pci0000:00/0000:00:12.0/0000:01:02.0/graphics/fb1
-loginctl attach seat-qemu \
-        /sys/devices/pci0000:00/0000:00:12.0/0000:01:0f.0/usb2
-
-Use "loginctl seat-status seat-qemu" to check the result.  It isn't
-needed to assign the usb devices to the head individually, assigning a
-usb (root) hub will automatically assign all usb devices connected to
-it too.
-
-BTW: loginctl writes udev rules to /etc/udev/rules.d to make these
-device assignments permanent, so you need to do this only once.
-
-Now simply restart gdm (rebooting will do too), and a login screen
-should show up on the second head.
+Now we'll have to configure the guest.  Boot and login.  "lspci -vt"
+should list the pci bridge with the display adapter and usb controller:
+
+    [root@fedora ~]# lspci -vt
+    -[0000:00]-+-00.0  Intel Corporation 440FX - 82441FX PMC [Natoma]
+               [ ... ]
+               \-12.0-[01]--+-02.0  Device 1234:1111
+                            \-0f.0  NEC Corporation USB 3.0 Host Controller
+
+Good.  Now lets tell the system that the pci bridge and all devices
+below it belong to a separate seat by dropping a file into
+/etc/udev/rules.d:
+
+    [root@fedora ~]# cat /etc/udev/rules.d/70-qemu-autoseat.rules
+    SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:12.0", TAG+="seat", ENV{ID_AUTOSEAT}="1"
+
+Reboot.  System should come up with two seats.  With loginctl you can
+check the configuration:
+
+    [root@fedora ~]# loginctl list-seats
+    SEAT
+    seat0
+    seat-pci-pci-0000_00_12_0
+
+    2 seats listed.
+
+You can use "loginctl seat-status seat-pci-pci-0000_00_12_0" to list
+the devices attached to the seat.
+
+Background info is here:
+  http://www.freedesktop.org/wiki/Software/systemd/multiseat/
 
 Enjoy!
 
index f74612f468dd4a11eb88fb4bfafeb5391d492a2a..edff5f22a8b79aa22a74d8e2978fc2b13b77e59f 100644 (file)
@@ -35,7 +35,8 @@ which will return a dictionary containing:
 
   o A key named last-update, which contains the last stats update
     timestamp in seconds. Since this timestamp is generated by the host,
-    a buggy guest can't influence its value
+    a buggy guest can't influence its value. The value is 0 if the guest
+    has not updated the stats (yet).
 
 It's also important to note the following:
 
@@ -49,7 +50,7 @@ It's also important to note the following:
 
  - Polling can be enabled even if the guest doesn't have stats support
    or the balloon driver wasn't loaded in the guest. If this is the case
-   and stats are queried, an error will be returned
+   and stats are queried, last-update will be 0.
 
  - The polling timer is only re-armed when the guest responds to the
    statistics request. This means that if a (buggy) guest doesn't ever
index 15a4983eee35a83fd95b3fb09c4e25d695069524..653762af1a3d94554573a1cb8a3662880382814e 100644 (file)
@@ -34,7 +34,7 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
 
     len = strlen(s->tag);
     cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
-    stw_raw(&cfg->tag_len, len);
+    stw_p(&cfg->tag_len, len);
     /* We don't copy the terminating null to config space */
     memcpy(cfg->tag, s->tag, len);
     memcpy(config, cfg, s->config_size);
index 82772c657e4d469bd5e0c21630215c10ac1f5042..4f092d6446ccd84416b1ff3ad7915da63718787b 100644 (file)
@@ -239,8 +239,9 @@ static void n800_key_event(void *opaque, int keycode)
     int code = s->keymap[keycode & 0x7f];
 
     if (code == -1) {
-        if ((keycode & 0x7f) == RETU_KEYCODE)
+        if ((keycode & 0x7f) == RETU_KEYCODE) {
             retu_key_event(s->retu, !(keycode & 0x80));
+        }
         return;
     }
 
@@ -280,11 +281,14 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
     s->ts.opaque = s->ts.chip->opaque;
     s->ts.txrx = tsc210x_txrx;
 
-    for (i = 0; i < 0x80; i ++)
+    for (i = 0; i < 0x80; i++) {
         s->keymap[i] = -1;
-    for (i = 0; i < 0x10; i ++)
-        if (n800_keys[i] >= 0)
+    }
+    for (i = 0; i < 0x10; i++) {
+        if (n800_keys[i] >= 0) {
             s->keymap[n800_keys[i]] = i;
+        }
+    }
 
     qemu_add_kbd_event_handler(n800_key_event, s);
 
@@ -308,8 +312,9 @@ static void n810_key_event(void *opaque, int keycode)
     int code = s->keymap[keycode & 0x7f];
 
     if (code == -1) {
-        if ((keycode & 0x7f) == RETU_KEYCODE)
+        if ((keycode & 0x7f) == RETU_KEYCODE) {
             retu_key_event(s->retu, !(keycode & 0x80));
+        }
         return;
     }
 
@@ -388,11 +393,14 @@ static void n810_kbd_setup(struct n800_s *s)
     qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
     int i;
 
-    for (i = 0; i < 0x80; i ++)
+    for (i = 0; i < 0x80; i++) {
         s->keymap[i] = -1;
-    for (i = 0; i < 0x80; i ++)
-        if (n810_keys[i] > 0)
+    }
+    for (i = 0; i < 0x80; i++) {
+        if (n810_keys[i] > 0) {
             s->keymap[n810_keys[i]] = i;
+        }
+    }
 
     qemu_add_kbd_event_handler(n810_key_event, s);
 
@@ -449,17 +457,20 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
     struct mipid_s *s = (struct mipid_s *) opaque;
     uint8_t ret;
 
-    if (len > 9)
+    if (len > 9) {
         hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
+    }
 
-    if (s->p >= ARRAY_SIZE(s->resp))
+    if (s->p >= ARRAY_SIZE(s->resp)) {
         ret = 0;
-    else
-        ret = s->resp[s->p ++];
-    if (s->pm --> 0)
+    } else {
+        ret = s->resp[s->p++];
+    }
+    if (s->pm-- > 0) {
         s->param[s->pm] = cmd;
-    else
+    } else {
         s->cmd = cmd;
+    }
 
     switch (s->cmd) {
     case 0x00: /* NOP */
@@ -560,15 +571,17 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
         goto bad_cmd;
 
     case 0x25: /* WRCNTR */
-        if (s->pm < 0)
+        if (s->pm < 0) {
             s->pm = 1;
+        }
         goto bad_cmd;
 
     case 0x26: /* GAMSET */
-        if (!s->pm)
+        if (!s->pm) {
             s->gamma = ffs(s->param[0] & 0xf) - 1;
-        else if (s->pm < 0)
+        } else if (s->pm < 0) {
             s->pm = 1;
+        }
         break;
 
     case 0x28: /* DISPOFF */
@@ -591,10 +604,11 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
         s->te = 0;
         break;
     case 0x35: /* TEON */
-        if (!s->pm)
+        if (!s->pm) {
             s->te = 1;
-        else if (s->pm < 0)
+        } else if (s->pm < 0) {
             s->pm = 1;
+        }
         break;
 
     case 0x36: /* MADCTR */
@@ -613,8 +627,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 
     case 0xb0: /* CLKINT / DISCTL */
     case 0xb1: /* CLKEXT */
-        if (s->pm < 0)
+        if (s->pm < 0) {
             s->pm = 2;
+        }
         break;
 
     case 0xb4: /* FRMSEL */
@@ -635,8 +650,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
         break;
 
     case 0xc2: /* IFMOD */
-        if (s->pm < 0)
+        if (s->pm < 0) {
             s->pm = 2;
+        }
         break;
 
     case 0xc6: /* PWRCTL */
@@ -834,118 +850,119 @@ static void n800_setup_nolo_tags(void *sram_base)
 
     strcpy((void *) (p + 8), "F5");
 
-    stl_raw(p + 10, 0x04f70000);
+    stl_p(p + 10, 0x04f70000);
     strcpy((void *) (p + 9), "RX-34");
 
     /* RAM size in MB? */
-    stl_raw(p + 12, 0x80);
+    stl_p(p + 12, 0x80);
 
     /* Pointer to the list of tags */
-    stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
+    stl_p(p + 13, OMAP2_SRAM_BASE + 0x9000);
 
     /* The NOLO tags start here */
     p = sram_base + 0x9000;
 #define ADD_TAG(tag, len)                              \
-    stw_raw((uint16_t *) p + 0, tag);                  \
-    stw_raw((uint16_t *) p + 1, len); p ++;            \
-    stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
+    stw_p((uint16_t *) p + 0, tag);                    \
+    stw_p((uint16_t *) p + 1, len); p++;               \
+    stl_p(p++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
 
     /* OMAP STI console? Pin out settings? */
     ADD_TAG(0x6e01, 414);
-    for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
-        stl_raw(v ++, n800_pinout[i]);
+    for (i = 0; i < ARRAY_SIZE(n800_pinout); i++) {
+        stl_p(v++, n800_pinout[i]);
+    }
 
     /* Kernel memsize? */
     ADD_TAG(0x6e05, 1);
-    stl_raw(v ++, 2);
+    stl_p(v++, 2);
 
     /* NOLO serial console */
     ADD_TAG(0x6e02, 4);
-    stl_raw(v ++, XLDR_LL_UART);       /* UART number (1 - 3) */
+    stl_p(v++, XLDR_LL_UART);          /* UART number (1 - 3) */
 
 #if 0
     /* CBUS settings (Retu/AVilma) */
     ADD_TAG(0x6e03, 6);
-    stw_raw((uint16_t *) v + 0, 65);   /* CBUS GPIO0 */
-    stw_raw((uint16_t *) v + 1, 66);   /* CBUS GPIO1 */
-    stw_raw((uint16_t *) v + 2, 64);   /* CBUS GPIO2 */
+    stw_p((uint16_t *) v + 0, 65);     /* CBUS GPIO0 */
+    stw_p((uint16_t *) v + 1, 66);     /* CBUS GPIO1 */
+    stw_p((uint16_t *) v + 2, 64);     /* CBUS GPIO2 */
     v += 2;
 #endif
 
     /* Nokia ASIC BB5 (Retu/Tahvo) */
     ADD_TAG(0x6e0a, 4);
-    stw_raw((uint16_t *) v + 0, 111);  /* "Retu" interrupt GPIO */
-    stw_raw((uint16_t *) v + 1, 108);  /* "Tahvo" interrupt GPIO */
-    v ++;
+    stw_p((uint16_t *) v + 0, 111);    /* "Retu" interrupt GPIO */
+    stw_p((uint16_t *) v + 1, 108);    /* "Tahvo" interrupt GPIO */
+    v++;
 
     /* LCD console? */
     ADD_TAG(0x6e04, 4);
-    stw_raw((uint16_t *) v + 0, 30);   /* ??? */
-    stw_raw((uint16_t *) v + 1, 24);   /* ??? */
-    v ++;
+    stw_p((uint16_t *) v + 0, 30);     /* ??? */
+    stw_p((uint16_t *) v + 1, 24);     /* ??? */
+    v++;
 
 #if 0
     /* LCD settings */
     ADD_TAG(0x6e06, 2);
-    stw_raw((uint16_t *) (v ++), 15);  /* ??? */
+    stw_p((uint16_t *) (v++), 15);     /* ??? */
 #endif
 
     /* I^2C (Menelaus) */
     ADD_TAG(0x6e07, 4);
-    stl_raw(v ++, 0x00720000);         /* ??? */
+    stl_p(v++, 0x00720000);            /* ??? */
 
     /* Unknown */
     ADD_TAG(0x6e0b, 6);
-    stw_raw((uint16_t *) v + 0, 94);   /* ??? */
-    stw_raw((uint16_t *) v + 1, 23);   /* ??? */
-    stw_raw((uint16_t *) v + 2, 0);    /* ??? */
+    stw_p((uint16_t *) v + 0, 94);     /* ??? */
+    stw_p((uint16_t *) v + 1, 23);     /* ??? */
+    stw_p((uint16_t *) v + 2, 0);      /* ??? */
     v += 2;
 
     /* OMAP gpio switch info */
     ADD_TAG(0x6e0c, 80);
     strcpy((void *) v, "bat_cover");   v += 3;
-    stw_raw((uint16_t *) v + 0, 110);  /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 1);    /* GPIO num ??? */
+    stw_p((uint16_t *) v + 0, 110);    /* GPIO num ??? */
+    stw_p((uint16_t *) v + 1, 1);      /* GPIO num ??? */
     v += 2;
     strcpy((void *) v, "cam_act");     v += 3;
-    stw_raw((uint16_t *) v + 0, 95);   /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 32);   /* GPIO num ??? */
+    stw_p((uint16_t *) v + 0, 95);     /* GPIO num ??? */
+    stw_p((uint16_t *) v + 1, 32);     /* GPIO num ??? */
     v += 2;
     strcpy((void *) v, "cam_turn");    v += 3;
-    stw_raw((uint16_t *) v + 0, 12);   /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 33);   /* GPIO num ??? */
+    stw_p((uint16_t *) v + 0, 12);     /* GPIO num ??? */
+    stw_p((uint16_t *) v + 1, 33);     /* GPIO num ??? */
     v += 2;
     strcpy((void *) v, "headphone");   v += 3;
-    stw_raw((uint16_t *) v + 0, 107);  /* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 17);   /* GPIO num ??? */
+    stw_p((uint16_t *) v + 0, 107);    /* GPIO num ??? */
+    stw_p((uint16_t *) v + 1, 17);     /* GPIO num ??? */
     v += 2;
 
     /* Bluetooth */
     ADD_TAG(0x6e0e, 12);
-    stl_raw(v ++, 0x5c623d01);         /* ??? */
-    stl_raw(v ++, 0x00000201);         /* ??? */
-    stl_raw(v ++, 0x00000000);         /* ??? */
+    stl_p(v++, 0x5c623d01);            /* ??? */
+    stl_p(v++, 0x00000201);            /* ??? */
+    stl_p(v++, 0x00000000);            /* ??? */
 
     /* CX3110x WLAN settings */
     ADD_TAG(0x6e0f, 8);
-    stl_raw(v ++, 0x00610025);         /* ??? */
-    stl_raw(v ++, 0xffff0057);         /* ??? */
+    stl_p(v++, 0x00610025);            /* ??? */
+    stl_p(v++, 0xffff0057);            /* ??? */
 
     /* MMC host settings */
     ADD_TAG(0x6e10, 12);
-    stl_raw(v ++, 0xffff000f);         /* ??? */
-    stl_raw(v ++, 0xffffffff);         /* ??? */
-    stl_raw(v ++, 0x00000060);         /* ??? */
+    stl_p(v++, 0xffff000f);            /* ??? */
+    stl_p(v++, 0xffffffff);            /* ??? */
+    stl_p(v++, 0x00000060);            /* ??? */
 
     /* OneNAND chip select */
     ADD_TAG(0x6e11, 10);
-    stl_raw(v ++, 0x00000401);         /* ??? */
-    stl_raw(v ++, 0x0002003a);         /* ??? */
-    stl_raw(v ++, 0x00000002);         /* ??? */
+    stl_p(v++, 0x00000401);            /* ??? */
+    stl_p(v++, 0x0002003a);            /* ??? */
+    stl_p(v++, 0x00000002);            /* ??? */
 
     /* TEA5761 sensor settings */
     ADD_TAG(0x6e12, 2);
-    stl_raw(v ++, 93);                 /* GPIO num ??? */
+    stl_p(v++, 93);                    /* GPIO num ??? */
 
 #if 0
     /* Unknown tag */
@@ -956,8 +973,8 @@ static void n800_setup_nolo_tags(void *sram_base)
 #endif
 
     /* End of the list */
-    stl_raw(p ++, 0x00000000);
-    stl_raw(p ++, 0x00000000);
+    stl_p(p++, 0x00000000);
+    stl_p(p++, 0x00000000);
 }
 
 /* This task is normally performed by the bootloader.  If we're loading
@@ -1032,8 +1049,9 @@ static void n8x0_boot_init(void *opaque)
     s->mpu->cpu->env.GE = 0x5;
 
     /* If the machine has a slided keyboard, open it */
-    if (s->kbd)
+    if (s->kbd) {
         qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
+    }
 }
 
 #define OMAP_TAG_NOKIA_BT      0x4e01
@@ -1119,112 +1137,112 @@ static int n8x0_atag_setup(void *p, int model)
 
     w = p;
 
-    stw_raw(w ++, OMAP_TAG_UART);              /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
-    w ++;
+    stw_p(w++, OMAP_TAG_UART);                 /* u16 tag */
+    stw_p(w++, 4);                             /* u16 len */
+    stw_p(w++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
+    w++;
 
 #if 0
-    stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);    /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, XLDR_LL_UART + 1);           /* u8 console_uart */
-    stw_raw(w ++, 115200);                     /* u32 console_speed */
+    stw_p(w++, OMAP_TAG_SERIAL_CONSOLE);       /* u16 tag */
+    stw_p(w++, 4);                             /* u16 len */
+    stw_p(w++, XLDR_LL_UART + 1);              /* u8 console_uart */
+    stw_p(w++, 115200);                                /* u32 console_speed */
 #endif
 
-    stw_raw(w ++, OMAP_TAG_LCD);               /* u16 tag */
-    stw_raw(w ++, 36);                         /* u16 len */
+    stw_p(w++, OMAP_TAG_LCD);                  /* u16 tag */
+    stw_p(w++, 36);                            /* u16 len */
     strcpy((void *) w, "QEMU LCD panel");      /* char panel_name[16] */
     w += 8;
     strcpy((void *) w, "blizzard");            /* char ctrl_name[16] */
     w += 8;
-    stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);   /* TODO: n800 s16 nreset_gpio */
-    stw_raw(w ++, 24);                         /* u8 data_lines */
+    stw_p(w++, N810_BLIZZARD_RESET_GPIO);      /* TODO: n800 s16 nreset_gpio */
+    stw_p(w++, 24);                            /* u8 data_lines */
 
-    stw_raw(w ++, OMAP_TAG_CBUS);              /* u16 tag */
-    stw_raw(w ++, 8);                          /* u16 len */
-    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);         /* s16 clk_gpio */
-    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);         /* s16 dat_gpio */
-    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);         /* s16 sel_gpio */
-    w ++;
+    stw_p(w++, OMAP_TAG_CBUS);                 /* u16 tag */
+    stw_p(w++, 8);                             /* u16 len */
+    stw_p(w++, N8X0_CBUS_CLK_GPIO);            /* s16 clk_gpio */
+    stw_p(w++, N8X0_CBUS_DAT_GPIO);            /* s16 dat_gpio */
+    stw_p(w++, N8X0_CBUS_SEL_GPIO);            /* s16 sel_gpio */
+    w++;
 
-    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);       /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, N8X0_RETU_GPIO);             /* s16 retu_irq_gpio */
-    stw_raw(w ++, N8X0_TAHVO_GPIO);            /* s16 tahvo_irq_gpio */
+    stw_p(w++, OMAP_TAG_EM_ASIC_BB5);          /* u16 tag */
+    stw_p(w++, 4);                             /* u16 len */
+    stw_p(w++, N8X0_RETU_GPIO);                        /* s16 retu_irq_gpio */
+    stw_p(w++, N8X0_TAHVO_GPIO);               /* s16 tahvo_irq_gpio */
 
     gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
-    for (; gpiosw->name; gpiosw ++) {
-        stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);   /* u16 tag */
-        stw_raw(w ++, 20);                     /* u16 len */
+    for (; gpiosw->name; gpiosw++) {
+        stw_p(w++, OMAP_TAG_GPIO_SWITCH);      /* u16 tag */
+        stw_p(w++, 20);                                /* u16 len */
         strcpy((void *) w, gpiosw->name);      /* char name[12] */
         w += 6;
-        stw_raw(w ++, gpiosw->line);           /* u16 gpio */
-        stw_raw(w ++, gpiosw->type);
-        stw_raw(w ++, 0);
-        stw_raw(w ++, 0);
+        stw_p(w++, gpiosw->line);              /* u16 gpio */
+        stw_p(w++, gpiosw->type);
+        stw_p(w++, 0);
+        stw_p(w++, 0);
     }
 
-    stw_raw(w ++, OMAP_TAG_NOKIA_BT);          /* u16 tag */
-    stw_raw(w ++, 12);                         /* u16 len */
+    stw_p(w++, OMAP_TAG_NOKIA_BT);             /* u16 tag */
+    stw_p(w++, 12);                            /* u16 len */
     b = (void *) w;
-    stb_raw(b ++, 0x01);                       /* u8 chip_type (CSR) */
-    stb_raw(b ++, N8X0_BT_WKUP_GPIO);          /* u8 bt_wakeup_gpio */
-    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);     /* u8 host_wakeup_gpio */
-    stb_raw(b ++, N8X0_BT_RESET_GPIO);         /* u8 reset_gpio */
-    stb_raw(b ++, BT_UART + 1);                        /* u8 bt_uart */
+    stb_p(b++, 0x01);                          /* u8 chip_type (CSR) */
+    stb_p(b++, N8X0_BT_WKUP_GPIO);             /* u8 bt_wakeup_gpio */
+    stb_p(b++, N8X0_BT_HOST_WKUP_GPIO);                /* u8 host_wakeup_gpio */
+    stb_p(b++, N8X0_BT_RESET_GPIO);            /* u8 reset_gpio */
+    stb_p(b++, BT_UART + 1);                   /* u8 bt_uart */
     memcpy(b, &n8x0_bd_addr, 6);               /* u8 bd_addr[6] */
     b += 6;
-    stb_raw(b ++, 0x02);                       /* u8 bt_sysclk (38.4) */
+    stb_p(b++, 0x02);                          /* u8 bt_sysclk (38.4) */
     w = (void *) b;
 
-    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);      /* u16 tag */
-    stw_raw(w ++, 8);                          /* u16 len */
-    stw_raw(w ++, 0x25);                       /* u8 chip_type */
-    stw_raw(w ++, N8X0_WLAN_PWR_GPIO);         /* s16 power_gpio */
-    stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);         /* s16 irq_gpio */
-    stw_raw(w ++, -1);                         /* s16 spi_cs_gpio */
+    stw_p(w++, OMAP_TAG_WLAN_CX3110X);         /* u16 tag */
+    stw_p(w++, 8);                             /* u16 len */
+    stw_p(w++, 0x25);                          /* u8 chip_type */
+    stw_p(w++, N8X0_WLAN_PWR_GPIO);            /* s16 power_gpio */
+    stw_p(w++, N8X0_WLAN_IRQ_GPIO);            /* s16 irq_gpio */
+    stw_p(w++, -1);                            /* s16 spi_cs_gpio */
 
-    stw_raw(w ++, OMAP_TAG_MMC);               /* u16 tag */
-    stw_raw(w ++, 16);                         /* u16 len */
+    stw_p(w++, OMAP_TAG_MMC);                  /* u16 tag */
+    stw_p(w++, 16);                            /* u16 len */
     if (model == 810) {
-        stw_raw(w ++, 0x23f);                  /* unsigned flags */
-        stw_raw(w ++, -1);                     /* s16 power_pin */
-        stw_raw(w ++, -1);                     /* s16 switch_pin */
-        stw_raw(w ++, -1);                     /* s16 wp_pin */
-        stw_raw(w ++, 0x240);                  /* unsigned flags */
-        stw_raw(w ++, 0xc000);                 /* s16 power_pin */
-        stw_raw(w ++, 0x0248);                 /* s16 switch_pin */
-        stw_raw(w ++, 0xc000);                 /* s16 wp_pin */
+        stw_p(w++, 0x23f);                     /* unsigned flags */
+        stw_p(w++, -1);                                /* s16 power_pin */
+        stw_p(w++, -1);                                /* s16 switch_pin */
+        stw_p(w++, -1);                                /* s16 wp_pin */
+        stw_p(w++, 0x240);                     /* unsigned flags */
+        stw_p(w++, 0xc000);                    /* s16 power_pin */
+        stw_p(w++, 0x0248);                    /* s16 switch_pin */
+        stw_p(w++, 0xc000);                    /* s16 wp_pin */
     } else {
-        stw_raw(w ++, 0xf);                    /* unsigned flags */
-        stw_raw(w ++, -1);                     /* s16 power_pin */
-        stw_raw(w ++, -1);                     /* s16 switch_pin */
-        stw_raw(w ++, -1);                     /* s16 wp_pin */
-        stw_raw(w ++, 0);                      /* unsigned flags */
-        stw_raw(w ++, 0);                      /* s16 power_pin */
-        stw_raw(w ++, 0);                      /* s16 switch_pin */
-        stw_raw(w ++, 0);                      /* s16 wp_pin */
+        stw_p(w++, 0xf);                       /* unsigned flags */
+        stw_p(w++, -1);                                /* s16 power_pin */
+        stw_p(w++, -1);                                /* s16 switch_pin */
+        stw_p(w++, -1);                                /* s16 wp_pin */
+        stw_p(w++, 0);                         /* unsigned flags */
+        stw_p(w++, 0);                         /* s16 power_pin */
+        stw_p(w++, 0);                         /* s16 switch_pin */
+        stw_p(w++, 0);                         /* s16 wp_pin */
     }
 
-    stw_raw(w ++, OMAP_TAG_TEA5761);           /* u16 tag */
-    stw_raw(w ++, 4);                          /* u16 len */
-    stw_raw(w ++, N8X0_TEA5761_CS_GPIO);       /* u16 enable_gpio */
-    w ++;
+    stw_p(w++, OMAP_TAG_TEA5761);              /* u16 tag */
+    stw_p(w++, 4);                             /* u16 len */
+    stw_p(w++, N8X0_TEA5761_CS_GPIO);          /* u16 enable_gpio */
+    w++;
 
     partition = (model == 810) ? n810_part_info : n800_part_info;
-    for (; partition->name; partition ++) {
-        stw_raw(w ++, OMAP_TAG_PARTITION);     /* u16 tag */
-        stw_raw(w ++, 28);                     /* u16 len */
+    for (; partition->name; partition++) {
+        stw_p(w++, OMAP_TAG_PARTITION);                /* u16 tag */
+        stw_p(w++, 28);                                /* u16 len */
         strcpy((void *) w, partition->name);   /* char name[16] */
         l = (void *) (w + 8);
-        stl_raw(l ++, partition->size);                /* unsigned int size */
-        stl_raw(l ++, partition->offset);      /* unsigned int offset */
-        stl_raw(l ++, partition->mask);                /* unsigned int mask_flags */
+        stl_p(l++, partition->size);           /* unsigned int size */
+        stl_p(l++, partition->offset);         /* unsigned int offset */
+        stl_p(l++, partition->mask);           /* unsigned int mask_flags */
         w = (void *) l;
     }
 
-    stw_raw(w ++, OMAP_TAG_BOOT_REASON);       /* u16 tag */
-    stw_raw(w ++, 12);                         /* u16 len */
+    stw_p(w++, OMAP_TAG_BOOT_REASON);          /* u16 tag */
+    stw_p(w++, 12);                            /* u16 len */
 #if 0
     strcpy((void *) w, "por");                 /* char reason_str[12] */
     strcpy((void *) w, "charger");             /* char reason_str[12] */
@@ -1242,15 +1260,15 @@ static int n8x0_atag_setup(void *p, int model)
     w += 6;
 
     tag = (model == 810) ? "RX-44" : "RX-34";
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
-    stw_raw(w ++, 24);                         /* u16 len */
+    stw_p(w++, OMAP_TAG_VERSION_STR);          /* u16 tag */
+    stw_p(w++, 24);                            /* u16 len */
     strcpy((void *) w, "product");             /* char component[12] */
     w += 6;
     strcpy((void *) w, tag);                   /* char version[12] */
     w += 6;
 
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
-    stw_raw(w ++, 24);                         /* u16 len */
+    stw_p(w++, OMAP_TAG_VERSION_STR);          /* u16 tag */
+    stw_p(w++, 24);                            /* u16 len */
     strcpy((void *) w, "hw-build");            /* char component[12] */
     w += 6;
     strcpy((void *) w, "QEMU ");
@@ -1258,8 +1276,8 @@ static int n8x0_atag_setup(void *p, int model)
     w += 6;
 
     tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);       /* u16 tag */
-    stw_raw(w ++, 24);                         /* u16 len */
+    stw_p(w++, OMAP_TAG_VERSION_STR);          /* u16 tag */
+    stw_p(w++, 24);                            /* u16 len */
     strcpy((void *) w, "nolo");                        /* char component[12] */
     w += 6;
     strcpy((void *) w, tag);                   /* char version[12] */
@@ -1315,9 +1333,9 @@ static void n8x0_init(MachineState *machine,
     n8x0_gpio_setup(s);
     n8x0_nand_setup(s);
     n8x0_i2c_setup(s);
-    if (model == 800)
+    if (model == 800) {
         n800_tsc_kbd_setup(s);
-    else if (model == 810) {
+    else if (model == 810) {
         n810_tsc_setup(s);
         n810_kbd_setup(s);
     }
index 0b1446e2c4539e730d429a3d2bd5d55e45d1b02f..85aa8715bac28cf819960012798151736b95ab84 100644 (file)
@@ -494,12 +494,12 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 
     bdrv_get_geometry(s->bs, &capacity);
     memset(&blkcfg, 0, sizeof(blkcfg));
-    stq_raw(&blkcfg.capacity, capacity);
-    stl_raw(&blkcfg.seg_max, 128 - 2);
-    stw_raw(&blkcfg.cylinders, s->conf->cyls);
-    stl_raw(&blkcfg.blk_size, blk_size);
-    stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
-    stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
+    stq_p(&blkcfg.capacity, capacity);
+    stl_p(&blkcfg.seg_max, 128 - 2);
+    stw_p(&blkcfg.cylinders, s->conf->cyls);
+    stl_p(&blkcfg.blk_size, blk_size);
+    stw_p(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
+    stw_p(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
     blkcfg.heads = s->conf->heads;
     /*
      * We must ensure that the block device capacity is a multiple of
index 991c99fa6ebdc803212b8fab99c4be123332a824..acccc9cabdc8e31e83cf510cb5c14d74e60c98cd 100644 (file)
@@ -34,6 +34,7 @@
 typedef struct PCISerialState {
     PCIDevice dev;
     SerialState state;
+    uint8_t prog_if;
 } PCISerialState;
 
 typedef struct PCIMultiSerialState {
@@ -44,6 +45,7 @@ typedef struct PCIMultiSerialState {
     SerialState  state[PCI_SERIAL_MAX_PORTS];
     uint32_t     level[PCI_SERIAL_MAX_PORTS];
     qemu_irq     *irqs;
+    uint8_t      prog_if;
 } PCIMultiSerialState;
 
 static int serial_pci_init(PCIDevice *dev)
@@ -60,6 +62,7 @@ static int serial_pci_init(PCIDevice *dev)
         return -1;
     }
 
+    pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
     pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
     s->irq = pci_allocate_irq(&pci->dev);
 
@@ -101,6 +104,7 @@ static int multi_serial_pci_init(PCIDevice *dev)
     assert(pci->ports > 0);
     assert(pci->ports <= PCI_SERIAL_MAX_PORTS);
 
+    pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
     pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
     memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * pci->ports);
     pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
@@ -177,12 +181,14 @@ static const VMStateDescription vmstate_pci_multi_serial = {
 
 static Property serial_pci_properties[] = {
     DEFINE_PROP_CHR("chardev",  PCISerialState, state.chr),
+    DEFINE_PROP_UINT8("prog_if",  PCISerialState, prog_if, 0x02),
     DEFINE_PROP_END_OF_LIST(),
 };
 
 static Property multi_2x_serial_pci_properties[] = {
     DEFINE_PROP_CHR("chardev1",  PCIMultiSerialState, state[0].chr),
     DEFINE_PROP_CHR("chardev2",  PCIMultiSerialState, state[1].chr),
+    DEFINE_PROP_UINT8("prog_if",  PCIMultiSerialState, prog_if, 0x02),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -191,6 +197,7 @@ static Property multi_4x_serial_pci_properties[] = {
     DEFINE_PROP_CHR("chardev2",  PCIMultiSerialState, state[1].chr),
     DEFINE_PROP_CHR("chardev3",  PCIMultiSerialState, state[2].chr),
     DEFINE_PROP_CHR("chardev4",  PCIMultiSerialState, state[3].chr),
+    DEFINE_PROP_UINT8("prog_if",  PCIMultiSerialState, prog_if, 0x02),
     DEFINE_PROP_END_OF_LIST(),
 };
 
index b0d1d04af7556922c906edbb044d01cbbeefb6ce..f7c3cae2fac9558a5633cb1e9ac9f639dd45eba4 100644 (file)
@@ -87,6 +87,11 @@ static void uart_update_status(XilinxUARTLite *s)
     s->regs[R_STATUS] = r;
 }
 
+static void xilinx_uartlite_reset(DeviceState *dev)
+{
+    uart_update_status(XILINX_UARTLITE(dev));
+}
+
 static uint64_t
 uart_read(void *opaque, hwaddr addr, unsigned int size)
 {
@@ -196,34 +201,39 @@ static void uart_event(void *opaque, int event)
 
 }
 
-static int xilinx_uartlite_init(SysBusDevice *dev)
+static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
 {
     XilinxUARTLite *s = XILINX_UARTLITE(dev);
 
-    sysbus_init_irq(dev, &s->irq);
-
-    uart_update_status(s);
-    memory_region_init_io(&s->mmio, OBJECT(s), &uart_ops, s,
-                          "xlnx.xps-uartlite", R_MAX * 4);
-    sysbus_init_mmio(dev, &s->mmio);
-
     s->chr = qemu_char_get_next_serial();
     if (s->chr)
         qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
-    return 0;
+}
+
+static void xilinx_uartlite_init(Object *obj)
+{
+    XilinxUARTLite *s = XILINX_UARTLITE(obj);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+    memory_region_init_io(&s->mmio, obj, &uart_ops, s,
+                          "xlnx.xps-uartlite", R_MAX * 4);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 }
 
 static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
-    sdc->init = xilinx_uartlite_init;
+    dc->reset = xilinx_uartlite_reset;
+    dc->realize = xilinx_uartlite_realize;
 }
 
 static const TypeInfo xilinx_uartlite_info = {
     .name          = TYPE_XILINX_UARTLITE,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(XilinxUARTLite),
+    .instance_init = xilinx_uartlite_init,
     .class_init    = xilinx_uartlite_class_init,
 };
 
index 404cf1843dd3b2dd2288976a9bb2fe9710e6bb67..de433b2e38892a4bea65499a768af9330091b368 100644 (file)
@@ -439,11 +439,27 @@ PropertyInfo qdev_prop_iothread = {
 static int qdev_add_one_global(QemuOpts *opts, void *opaque)
 {
     GlobalProperty *g;
+    ObjectClass *oc;
 
     g = g_malloc0(sizeof(*g));
     g->driver   = qemu_opt_get(opts, "driver");
     g->property = qemu_opt_get(opts, "property");
     g->value    = qemu_opt_get(opts, "value");
+    oc = object_class_by_name(g->driver);
+    if (oc) {
+        DeviceClass *dc = DEVICE_CLASS(oc);
+
+        if (dc->hotpluggable) {
+            /* If hotpluggable then skip not_used checking. */
+            g->not_used = false;
+        } else {
+            /* Maybe a typo. */
+            g->not_used = true;
+        }
+    } else {
+        /* Maybe a typo. */
+        g->not_used = true;
+    }
     qdev_prop_register_global(g);
     return 0;
 }
index d8cb5408c388afdc19a56efe83aeec8c8bc48a9a..3d12560f43e72d8e54fac1f5aafe8f2ec19905c1 100644 (file)
@@ -955,6 +955,23 @@ void qdev_prop_register_global_list(GlobalProperty *props)
     }
 }
 
+int qdev_prop_check_global(void)
+{
+    GlobalProperty *prop;
+    int ret = 0;
+
+    QTAILQ_FOREACH(prop, &global_props, next) {
+        if (!prop->not_used) {
+            continue;
+        }
+        ret = 1;
+        error_report("Warning: \"-global %s.%s=%s\" not used",
+                     prop->driver, prop->property, prop->value);
+
+    }
+    return ret;
+}
+
 void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
                                     Error **errp)
 {
@@ -966,6 +983,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
         if (strcmp(typename, prop->driver) != 0) {
             continue;
         }
+        prop->not_used = false;
         object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
         if (err != NULL) {
             error_propagate(errp, err);
index f5a8299e5e75c61a19a87fa822eda3f9c13546ec..65ef7a7fe6be4c09836708b2883edec272eb5611 100644 (file)
@@ -177,7 +177,7 @@ static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size)
         /* monitor ID 6, board type = 1 (color) */
         val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR;
         break;
-    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
+    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
         val = s->regs[addr - 0x10];
         break;
     default:
@@ -247,7 +247,7 @@ static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
             qemu_irq_lower(s->irq);
         }
         break;
-    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
+    case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
         s->regs[addr - 0x10] = val;
         break;
     default:
@@ -274,6 +274,20 @@ static const GraphicHwOps cg3_ops = {
     .gfx_update = cg3_update_display,
 };
 
+static void cg3_initfn(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    CG3State *s = CG3(obj);
+
+    memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
+    memory_region_set_readonly(&s->rom, true);
+    sysbus_init_mmio(sbd, &s->rom);
+
+    memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
+                          CG3_REG_SIZE);
+    sysbus_init_mmio(sbd, &s->reg);
+}
+
 static void cg3_realizefn(DeviceState *dev, Error **errp)
 {
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
@@ -282,11 +296,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
     char *fcode_filename;
 
     /* FCode ROM */
-    memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
     vmstate_register_ram_global(&s->rom);
-    memory_region_set_readonly(&s->rom, true);
-    sysbus_init_mmio(sbd, &s->rom);
-
     fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE);
     if (fcode_filename) {
         ret = load_image_targphys(fcode_filename, s->prom_addr,
@@ -296,10 +306,6 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
         }
     }
 
-    memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
-                          CG3_REG_SIZE);
-    sysbus_init_mmio(sbd, &s->reg);
-
     memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size);
     vmstate_register_ram_global(&s->vram_mem);
     sysbus_init_mmio(sbd, &s->vram_mem);
@@ -374,6 +380,7 @@ static const TypeInfo cg3_info = {
     .name          = TYPE_CG3,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(CG3State),
+    .instance_init = cg3_initfn,
     .class_init    = cg3_class_init,
 };
 
index 2fb96f83ae61766c9aed6e5f9c6b15d247464856..e5dd4471673a39e84326742b16fa722860e7ca88 100644 (file)
@@ -50,7 +50,7 @@ static void glue(draw_line2_, DEPTH)(void *opaque,
     uint8_t v, r, g, b;
 
     do {
-        v = ldub_raw((void *) s);
+        v = ldub_p((void *) s);
         r = (pal[v & 3] >> 4) & 0xf0;
         g = pal[v & 3] & 0xf0;
         b = (pal[v & 3] << 4) & 0xf0;
@@ -89,7 +89,7 @@ static void glue(draw_line4_, DEPTH)(void *opaque,
     uint8_t v, r, g, b;
 
     do {
-        v = ldub_raw((void *) s);
+        v = ldub_p((void *) s);
         r = (pal[v & 0xf] >> 4) & 0xf0;
         g = pal[v & 0xf] & 0xf0;
         b = (pal[v & 0xf] << 4) & 0xf0;
@@ -116,7 +116,7 @@ static void glue(draw_line8_, DEPTH)(void *opaque,
     uint8_t v, r, g, b;
 
     do {
-        v = ldub_raw((void *) s);
+        v = ldub_p((void *) s);
         r = (pal[v] >> 4) & 0xf0;
         g = pal[v] & 0xf0;
         b = (pal[v] << 4) & 0xf0;
@@ -136,7 +136,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
     uint8_t r, g, b;
 
     do {
-        v = lduw_raw((void *) s);
+        v = lduw_p((void *) s);
         r = (v >> 4) & 0xf0;
         g = v & 0xf0;
         b = (v << 4) & 0xf0;
@@ -159,7 +159,7 @@ static void glue(draw_line16_, DEPTH)(void *opaque,
     uint8_t r, g, b;
 
     do {
-        v = lduw_raw((void *) s);
+        v = lduw_p((void *) s);
         r = (v >> 8) & 0xf8;
         g = (v >> 3) & 0xfc;
         b = (v << 3) & 0xf8;
index d4cea9e150431657c4e74b79fb7bcddb151af318..f33e499be429d91ee412e3abc7111995f831a3ea 100644 (file)
@@ -47,7 +47,7 @@ static void glue(draw_line8_, PIXEL_NAME)(
 {
     uint8_t v, r, g, b;
     do {
-       v = ldub_raw(s);
+       v = ldub_p(s);
        r = (pal[v] >> 16) & 0xff;
        g = (pal[v] >>  8) & 0xff;
        b = (pal[v] >>  0) & 0xff;
@@ -64,7 +64,7 @@ static void glue(draw_line16_, PIXEL_NAME)(
     uint8_t r, g, b;
 
     do {
-       rgb565 = lduw_raw(s);
+       rgb565 = lduw_p(s);
        r = ((rgb565 >> 11) & 0x1f) << 3;
        g = ((rgb565 >>  5) & 0x3f) << 2;
        b = ((rgb565 >>  0) & 0x1f) << 3;
@@ -80,7 +80,7 @@ static void glue(draw_line32_, PIXEL_NAME)(
     uint8_t r, g, b;
 
     do {
-       ldub_raw(s);
+       ldub_p(s);
 #if defined(TARGET_WORDS_BIGENDIAN)
         r = s[1];
         g = s[2];
index 2551b677aa71662fbdb5430f4615956d63407ace..28c742cc248d3634178ea584cd4e36b33e3cb7a7 100644 (file)
@@ -530,8 +530,36 @@ static const GraphicHwOps tcx24_ops = {
     .gfx_update = tcx24_update_display,
 };
 
-static int tcx_init1(SysBusDevice *dev)
+static void tcx_initfn(Object *obj)
 {
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    TCXState *s = TCX(obj);
+
+    memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
+    memory_region_set_readonly(&s->rom, true);
+    sysbus_init_mmio(sbd, &s->rom);
+
+    /* DAC */
+    memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
+                          "tcx.dac", TCX_DAC_NREGS);
+    sysbus_init_mmio(sbd, &s->dac);
+
+    /* TEC (dummy) */
+    memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
+                          "tcx.tec", TCX_TEC_NREGS);
+    sysbus_init_mmio(sbd, &s->tec);
+
+    /* THC: NetBSD writes here even with 8-bit display: dummy */
+    memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
+                          TCX_THC_NREGS_24);
+    sysbus_init_mmio(sbd, &s->thc24);
+
+    return;
+}
+
+static void tcx_realizefn(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     TCXState *s = TCX(dev);
     ram_addr_t vram_offset = 0;
     int size, ret;
@@ -544,18 +572,13 @@ static int tcx_init1(SysBusDevice *dev)
     vram_base = memory_region_get_ram_ptr(&s->vram_mem);
 
     /* FCode ROM */
-    memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
     vmstate_register_ram_global(&s->rom);
-    memory_region_set_readonly(&s->rom, true);
-    sysbus_init_mmio(dev, &s->rom);
-
     fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, TCX_ROM_FILE);
     if (fcode_filename) {
         ret = load_image_targphys(fcode_filename, s->prom_addr,
                                   FCODE_MAX_ROM_SIZE);
         if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
-            fprintf(stderr, "tcx: could not load prom '%s'\n", TCX_ROM_FILE);
-            return -1;
+            error_report("tcx: could not load prom '%s'", TCX_ROM_FILE);
         }
     }
 
@@ -564,24 +587,10 @@ static int tcx_init1(SysBusDevice *dev)
     size = s->vram_size;
     memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit",
                              &s->vram_mem, vram_offset, size);
-    sysbus_init_mmio(dev, &s->vram_8bit);
+    sysbus_init_mmio(sbd, &s->vram_8bit);
     vram_offset += size;
     vram_base += size;
 
-    /* DAC */
-    memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
-                          "tcx.dac", TCX_DAC_NREGS);
-    sysbus_init_mmio(dev, &s->dac);
-
-    /* TEC (dummy) */
-    memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
-                          "tcx.tec", TCX_TEC_NREGS);
-    sysbus_init_mmio(dev, &s->tec);
-    /* THC: NetBSD writes here even with 8-bit display: dummy */
-    memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
-                          TCX_THC_NREGS_24);
-    sysbus_init_mmio(dev, &s->thc24);
-
     if (s->depth == 24) {
         /* 24-bit plane */
         size = s->vram_size * 4;
@@ -589,7 +598,7 @@ static int tcx_init1(SysBusDevice *dev)
         s->vram24_offset = vram_offset;
         memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit",
                                  &s->vram_mem, vram_offset, size);
-        sysbus_init_mmio(dev, &s->vram_24bit);
+        sysbus_init_mmio(sbd, &s->vram_24bit);
         vram_offset += size;
         vram_base += size;
 
@@ -599,20 +608,19 @@ static int tcx_init1(SysBusDevice *dev)
         s->cplane_offset = vram_offset;
         memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane",
                                  &s->vram_mem, vram_offset, size);
-        sysbus_init_mmio(dev, &s->vram_cplane);
+        sysbus_init_mmio(sbd, &s->vram_cplane);
 
         s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
     } else {
         /* THC 8 bit (dummy) */
         memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
                               TCX_THC_NREGS_8);
-        sysbus_init_mmio(dev, &s->thc8);
+        sysbus_init_mmio(sbd, &s->thc8);
 
         s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
     }
 
     qemu_console_resize(s->con, s->width, s->height);
-    return 0;
 }
 
 static Property tcx_properties[] = {
@@ -627,9 +635,8 @@ static Property tcx_properties[] = {
 static void tcx_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = tcx_init1;
+    dc->realize = tcx_realizefn;
     dc->reset = tcx_reset;
     dc->vmsd = &vmstate_tcx;
     dc->props = tcx_properties;
@@ -639,6 +646,7 @@ static const TypeInfo tcx_info = {
     .name          = TYPE_TCX,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(TCXState),
+    .instance_init = tcx_initfn,
     .class_init    = tcx_class_init,
 };
 
index 6cfae567b42de44f6b6ae45b0c5924bf8535c8d6..90ec9c208f8f665fb8cda55fa9596e4d50353cb4 100644 (file)
@@ -361,7 +361,7 @@ static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 
     w = width;
     do {
-        v = lduw_raw((void *)s);
+        v = lduw_p((void *)s);
         r = (v >> 7) & 0xf8;
         g = (v >> 2) & 0xf8;
         b = (v << 3) & 0xf8;
@@ -386,7 +386,7 @@ static void glue(vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
 
     w = width;
     do {
-        v = lduw_raw((void *)s);
+        v = lduw_p((void *)s);
         r = (v >> 8) & 0xf8;
         g = (v >> 3) & 0xfc;
         b = (v << 3) & 0xf8;
index 892aa025f4f3df4c5e54e0c5734cc4e34c98cf8e..bef25043895b7cb67c5e3f4499b561b1c55f67ca 100644 (file)
  */
 
 #include "qemu-common.h"
+#include "qemu/host-utils.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
+#include "sysemu/cpus.h"
 #include "hw/sysbus.h"
 #include "hw/kvm/clock.h"
 
@@ -34,6 +36,48 @@ typedef struct KVMClockState {
     bool clock_valid;
 } KVMClockState;
 
+struct pvclock_vcpu_time_info {
+    uint32_t   version;
+    uint32_t   pad0;
+    uint64_t   tsc_timestamp;
+    uint64_t   system_time;
+    uint32_t   tsc_to_system_mul;
+    int8_t     tsc_shift;
+    uint8_t    flags;
+    uint8_t    pad[2];
+} __attribute__((__packed__)); /* 32 bytes */
+
+static uint64_t kvmclock_current_nsec(KVMClockState *s)
+{
+    CPUState *cpu = first_cpu;
+    CPUX86State *env = cpu->env_ptr;
+    hwaddr kvmclock_struct_pa = env->system_time_msr & ~1ULL;
+    uint64_t migration_tsc = env->tsc;
+    struct pvclock_vcpu_time_info time;
+    uint64_t delta;
+    uint64_t nsec_lo;
+    uint64_t nsec_hi;
+    uint64_t nsec;
+
+    if (!(env->system_time_msr & 1ULL)) {
+        /* KVM clock not active */
+        return 0;
+    }
+
+    cpu_physical_memory_read(kvmclock_struct_pa, &time, sizeof(time));
+
+    assert(time.tsc_timestamp <= migration_tsc);
+    delta = migration_tsc - time.tsc_timestamp;
+    if (time.tsc_shift < 0) {
+        delta >>= -time.tsc_shift;
+    } else {
+        delta <<= time.tsc_shift;
+    }
+
+    mulu64(&nsec_lo, &nsec_hi, delta, time.tsc_to_system_mul);
+    nsec = (nsec_lo >> 32) | (nsec_hi << 32);
+    return nsec + time.system_time;
+}
 
 static void kvmclock_vm_state_change(void *opaque, int running,
                                      RunState state)
@@ -45,9 +89,15 @@ static void kvmclock_vm_state_change(void *opaque, int running,
 
     if (running) {
         struct kvm_clock_data data;
+        uint64_t time_at_migration = kvmclock_current_nsec(s);
 
         s->clock_valid = false;
 
+       /* We can't rely on the migrated clock value, just discard it */
+       if (time_at_migration) {
+               s->clock = time_at_migration;
+       }
+
         data.clock = s->clock;
         data.flags = 0;
         ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
@@ -75,6 +125,8 @@ static void kvmclock_vm_state_change(void *opaque, int running,
         if (s->clock_valid) {
             return;
         }
+
+        cpu_synchronize_all_states();
         ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
         if (ret < 0) {
             fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
index 76607181c38390ba69edba9333b67c068d10a011..b3bedde8b96bdafc756389b806e4e4fd3fbdca3b 100644 (file)
@@ -67,7 +67,7 @@ static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
 
 static struct {
     const char *vendor, *version, *date;
-    bool have_major_minor;
+    bool have_major_minor, uefi;
     uint8_t major, minor;
 } type0;
 
@@ -134,6 +134,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
         .name = "release",
         .type = QEMU_OPT_STRING,
         .help = "revision number",
+    },{
+        .name = "uefi",
+        .type = QEMU_OPT_BOOL,
+        .help = "uefi support",
     },
     { /* end of list */ }
 };
@@ -444,7 +448,7 @@ static bool smbios_skip_table(uint8_t type, bool required_table)
                                                                           \
         t->header.type = tbl_type;                                        \
         t->header.length = sizeof(*t);                                    \
-        t->header.handle = tbl_handle;                                    \
+        t->header.handle = cpu_to_le16(tbl_handle);                       \
     } while (0)
 
 #define SMBIOS_TABLE_SET_STR(tbl_type, field, value)                      \
@@ -491,19 +495,18 @@ static void smbios_build_type_0_table(void)
     SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
     SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
 
-    t->bios_starting_address_segment = 0xE800; /* hardcoded in SeaBIOS */
+    t->bios_starting_address_segment = cpu_to_le16(0xE800); /* from SeaBIOS */
 
     SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date);
 
     t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
 
-    /* BIOS characteristics not supported */
-    memset(t->bios_characteristics, 0, 8);
-    t->bios_characteristics[0] = 0x08;
-
-    /* Enable targeted content distribution (needed for SVVP, per SeaBIOS) */
+    t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
     t->bios_characteristics_extension_bytes[0] = 0;
-    t->bios_characteristics_extension_bytes[1] = 4;
+    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
+    if (type0.uefi) {
+        t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
+    }
 
     if (type0.have_major_minor) {
         t->system_bios_major_release = type0.major;
@@ -551,7 +554,7 @@ static void smbios_build_type_2_table(void)
     SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset);
     t->feature_flags = 0x01; /* Motherboard */
     SMBIOS_TABLE_SET_STR(2, location_str, type2.location);
-    t->chassis_handle = 0x300; /* Type 3 (System enclosure) */
+    t->chassis_handle = cpu_to_le16(0x300); /* Type 3 (System enclosure) */
     t->board_type = 0x0A; /* Motherboard */
     t->contained_element_count = 0;
 
@@ -571,7 +574,7 @@ static void smbios_build_type_3_table(void)
     t->power_supply_state = 0x03; /* Safe */
     t->thermal_state = 0x03; /* Safe */
     t->security_status = 0x02; /* Unknown */
-    t->oem_defined = 0;
+    t->oem_defined = cpu_to_le32(0);
     t->height = 0;
     t->number_of_power_cords = 0;
     t->contained_element_count = 0;
@@ -589,26 +592,27 @@ static void smbios_build_type_4_table(unsigned instance)
     snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
     SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
     t->processor_type = 0x03; /* CPU */
+    t->processor_family = 0x01; /* Other */
     SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
-    t->processor_id[0] = smbios_cpuid_version;
-    t->processor_id[1] = smbios_cpuid_features;
+    t->processor_id[0] = cpu_to_le32(smbios_cpuid_version);
+    t->processor_id[1] = cpu_to_le32(smbios_cpuid_features);
     SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
     t->voltage = 0;
-    t->external_clock = 0; /* Unknown */
-    t->max_speed = 0; /* Unknown */
-    t->current_speed = 0; /* Unknown */
+    t->external_clock = cpu_to_le16(0); /* Unknown */
+    t->max_speed = cpu_to_le16(0); /* Unknown */
+    t->current_speed = cpu_to_le16(0); /* Unknown */
     t->status = 0x41; /* Socket populated, CPU enabled */
     t->processor_upgrade = 0x01; /* Other */
-    t->l1_cache_handle = 0xFFFF; /* N/A */
-    t->l2_cache_handle = 0xFFFF; /* N/A */
-    t->l3_cache_handle = 0xFFFF; /* N/A */
+    t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
+    t->l2_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
+    t->l3_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
     SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
     SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
     SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
     t->core_count = t->core_enabled = smp_cores;
     t->thread_count = smp_threads;
-    t->processor_characteristics = 0x02; /* Unknown */
-    t->processor_family = t->processor_family2 = 0x01; /* Other */
+    t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
+    t->processor_family2 = cpu_to_le16(0x01); /* Other */
 
     SMBIOS_BUILD_TABLE_POST;
     smbios_type4_count++;
@@ -631,14 +635,14 @@ static void smbios_build_type_16_table(unsigned dimm_cnt)
     t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */
     size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB;
     if (size_kb < MAX_T16_STD_SZ) {
-        t->maximum_capacity = size_kb;
-        t->extended_maximum_capacity = 0;
+        t->maximum_capacity = cpu_to_le32(size_kb);
+        t->extended_maximum_capacity = cpu_to_le64(0);
     } else {
-        t->maximum_capacity = MAX_T16_STD_SZ;
-        t->extended_maximum_capacity = ram_size;
+        t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ);
+        t->extended_maximum_capacity = cpu_to_le64(ram_size);
     }
-    t->memory_error_information_handle = 0xFFFE; /* Not provided */
-    t->number_of_memory_devices = dimm_cnt;
+    t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
+    t->number_of_memory_devices = cpu_to_le16(dimm_cnt);
 
     SMBIOS_BUILD_TABLE_POST;
 }
@@ -653,18 +657,18 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
 
     SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
 
-    t->physical_memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
-    t->memory_error_information_handle = 0xFFFE; /* Not provided */
-    t->total_width = 0xFFFF; /* Unknown */
-    t->data_width = 0xFFFF; /* Unknown */
+    t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
+    t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
+    t->total_width = cpu_to_le16(0xFFFF); /* Unknown */
+    t->data_width = cpu_to_le16(0xFFFF); /* Unknown */
     size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB;
     if (size_mb < MAX_T17_STD_SZ) {
-        t->size = size_mb;
-        t->extended_size = 0;
+        t->size = cpu_to_le16(size_mb);
+        t->extended_size = cpu_to_le32(0);
     } else {
         assert(size_mb < MAX_T17_EXT_SZ);
-        t->size = MAX_T17_STD_SZ;
-        t->extended_size = size_mb;
+        t->size = cpu_to_le16(MAX_T17_STD_SZ);
+        t->extended_size = cpu_to_le32(size_mb);
     }
     t->form_factor = 0x09; /* DIMM */
     t->device_set = 0; /* Not in a set */
@@ -672,17 +676,17 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
     SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str);
     SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank);
     t->memory_type = 0x07; /* RAM */
-    t->type_detail = 0x02; /* Other */
-    t->speed = 0; /* Unknown */
+    t->type_detail = cpu_to_le16(0x02); /* Other */
+    t->speed = cpu_to_le16(0); /* Unknown */
     SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer);
     SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial);
     SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset);
     SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part);
     t->attributes = 0; /* Unknown */
-    t->configured_clock_speed = 0; /* Unknown */
-    t->minimum_voltage = 0; /* Unknown */
-    t->maximum_voltage = 0; /* Unknown */
-    t->configured_voltage = 0; /* Unknown */
+    t->configured_clock_speed = cpu_to_le16(0); /* Unknown */
+    t->minimum_voltage = cpu_to_le16(0); /* Unknown */
+    t->maximum_voltage = cpu_to_le16(0); /* Unknown */
+    t->configured_voltage = cpu_to_le16(0); /* Unknown */
 
     SMBIOS_BUILD_TABLE_POST;
 }
@@ -699,15 +703,16 @@ static void smbios_build_type_19_table(unsigned instance,
     start_kb = start / ONE_KB;
     end_kb = end / ONE_KB;
     if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) {
-        t->starting_address = start_kb;
-        t->ending_address = end_kb;
-        t->extended_starting_address = t->extended_ending_address = 0;
+        t->starting_address = cpu_to_le32(start_kb);
+        t->ending_address = cpu_to_le32(end_kb);
+        t->extended_starting_address =
+            t->extended_ending_address = cpu_to_le64(0);
     } else {
-        t->starting_address = t->ending_address = UINT32_MAX;
-        t->extended_starting_address = start;
-        t->extended_ending_address = end;
+        t->starting_address = t->ending_address = cpu_to_le32(UINT32_MAX);
+        t->extended_starting_address = cpu_to_le64(start);
+        t->extended_ending_address = cpu_to_le64(end);
     }
-    t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
+    t->memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
     t->partition_width = 1; /* One device per row */
 
     SMBIOS_BUILD_TABLE_POST;
@@ -794,14 +799,14 @@ static void smbios_entry_point_setup(void)
     ep.smbios_bcd_revision = 0x28;
 
     /* set during table construction, but BIOS may override: */
-    ep.structure_table_length = smbios_tables_len;
-    ep.max_structure_size = smbios_table_max;
-    ep.number_of_structures = smbios_table_cnt;
+    ep.structure_table_length = cpu_to_le16(smbios_tables_len);
+    ep.max_structure_size = cpu_to_le16(smbios_table_max);
+    ep.number_of_structures = cpu_to_le16(smbios_table_cnt);
 
     /* BIOS must recalculate: */
     ep.checksum = 0;
     ep.intermediate_checksum = 0;
-    ep.structure_table_address = 0; /* where BIOS has copied smbios_tables */
+    ep.structure_table_address = cpu_to_le32(0);
 }
 
 void smbios_get_tables(uint8_t **tables, size_t *tables_len,
@@ -977,6 +982,7 @@ void smbios_entry_add(QemuOpts *opts)
             save_opt(&type0.vendor, opts, "vendor");
             save_opt(&type0.version, opts, "version");
             save_opt(&type0.date, opts, "date");
+            type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
 
             val = qemu_opt_get(opts, "release");
             if (val) {
index c3682f1b20231947a4feab8035f1f210fbd947d1..12804ab7299be7b551236236359ca35991c3d38a 100644 (file)
@@ -161,18 +161,16 @@ static void irq_handler(void *opaque, int irq, int level)
     update_irq(p);
 }
 
-static int xilinx_intc_init(SysBusDevice *sbd)
+static void xilinx_intc_init(Object *obj)
 {
-    DeviceState *dev = DEVICE(sbd);
-    struct xlx_pic *p = XILINX_INTC(dev);
+    struct xlx_pic *p = XILINX_INTC(obj);
 
-    qdev_init_gpio_in(dev, irq_handler, 32);
-    sysbus_init_irq(sbd, &p->parent_irq);
+    qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq);
 
-    memory_region_init_io(&p->mmio, OBJECT(p), &pic_ops, p, "xlnx.xps-intc",
+    memory_region_init_io(&p->mmio, obj, &pic_ops, p, "xlnx.xps-intc",
                           R_MAX * 4);
-    sysbus_init_mmio(sbd, &p->mmio);
-    return 0;
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
 }
 
 static Property xilinx_intc_properties[] = {
@@ -183,9 +181,7 @@ static Property xilinx_intc_properties[] = {
 static void xilinx_intc_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = xilinx_intc_init;
     dc->props = xilinx_intc_properties;
 }
 
@@ -193,6 +189,7 @@ static const TypeInfo xilinx_intc_info = {
     .name          = TYPE_XILINX_INTC,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct xlx_pic),
+    .instance_init = xilinx_intc_init,
     .class_init    = xilinx_intc_class_init,
 };
 
index 5ad7a410a94734a006c09a813215b5a5d5e8fd72..f7533ed2002aac8340f77976f5771e0db6147913 100644 (file)
@@ -178,24 +178,24 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_a
     /* Small bootloader */
     p = (uint32_t *) base;
 
-    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
-    stl_raw(p++, 0x00000000);                                      /* nop */
+    stl_p(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
+    stl_p(p++, 0x00000000);                                      /* nop */
 
     /* Second part of the bootloader */
     p = (uint32_t *) (base + 0x040);
 
-    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
-    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
-    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
-    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
-    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
-    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
-    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
-    stl_raw(p++, 0x03e00008);                                      /* jr ra */
-    stl_raw(p++, 0x00000000);                                      /* nop */
+    stl_p(p++, 0x3c040000);                                      /* lui a0, 0 */
+    stl_p(p++, 0x34840002);                                      /* ori a0, a0, 2 */
+    stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
+    stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
+    stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
+    stl_p(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
+    stl_p(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
+    stl_p(p++, 0x03e00008);                                      /* jr ra */
+    stl_p(p++, 0x00000000);                                      /* nop */
 }
 
 
index 9fe775ea881e1f9df06bb66bf0a69e7e974d0282..f4a7d47129526f6762eccc47251c8cf3cd27f928 100644 (file)
@@ -609,136 +609,136 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
 
     /* Small bootloader */
     p = (uint32_t *)base;
-    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
-    stl_raw(p++, 0x00000000);                                      /* nop */
+    stl_p(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+    stl_p(p++, 0x00000000);                                      /* nop */
 
     /* YAMON service vector */
-    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
-    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
-    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
-    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
-    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
-    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
-    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
-    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
-    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
-    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
-    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
+    stl_p(base + 0x500, 0xbfc00580);      /* start: */
+    stl_p(base + 0x504, 0xbfc0083c);      /* print_count: */
+    stl_p(base + 0x520, 0xbfc00580);      /* start: */
+    stl_p(base + 0x52c, 0xbfc00800);      /* flush_cache: */
+    stl_p(base + 0x534, 0xbfc00808);      /* print: */
+    stl_p(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
+    stl_p(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
+    stl_p(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
+    stl_p(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
+    stl_p(base + 0x548, 0xbfc00800);      /* reg_esr: */
+    stl_p(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
+    stl_p(base + 0x550, 0xbfc00800);      /* getchar: */
+    stl_p(base + 0x554, 0xbfc00800);      /* syscon_read: */
 
 
     /* Second part of the bootloader */
     p = (uint32_t *) (base + 0x580);
-    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
-    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
-    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
-    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
-    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
+    stl_p(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
+    stl_p(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
+    stl_p(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
+    stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
+    stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
+    stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
 
     /* Load BAR registers as done by YAMON */
-    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
+    stl_p(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
+    stl_p(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
 #else
-    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
+    stl_p(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
 #endif
-    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
+    stl_p(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
 
-    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
+    stl_p(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
+    stl_p(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
 #else
-    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
+    stl_p(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
 #endif
-    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
+    stl_p(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
 #ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
+    stl_p(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
 #else
-    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
+    stl_p(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
 #endif
-    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
+    stl_p(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
+    stl_p(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
 #else
-    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
+    stl_p(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
 #endif
-    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
+    stl_p(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
 #ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
+    stl_p(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
 #else
-    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
+    stl_p(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
 #endif
-    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
+    stl_p(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
 
 #ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
+    stl_p(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
 #else
-    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
+    stl_p(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
 #endif
-    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
+    stl_p(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
 #ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
+    stl_p(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
 #else
-    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
+    stl_p(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
 #endif
-    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
+    stl_p(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
 
     /* Jump to kernel code */
-    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
-    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
-    stl_raw(p++, 0x03e00008);                                      /* jr ra */
-    stl_raw(p++, 0x00000000);                                      /* nop */
+    stl_p(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
+    stl_p(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
+    stl_p(p++, 0x03e00008);                                      /* jr ra */
+    stl_p(p++, 0x00000000);                                      /* nop */
 
     /* YAMON subroutines */
     p = (uint32_t *) (base + 0x800);
-    stl_raw(p++, 0x03e00008);                                     /* jr ra */
-    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
+    stl_p(p++, 0x03e00008);                                     /* jr ra */
+    stl_p(p++, 0x24020000);                                     /* li v0,0 */
    /* 808 YAMON print */
-    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
-    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
-    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
-    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
-    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
-    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x08000205);                                     /* j 814 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
-    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    stl_p(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_p(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_p(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_p(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_p(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_p(p++, 0x10800005);                                     /* beqz a0,834 */
+    stl_p(p++, 0x00000000);                                     /* nop */
+    stl_p(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_p(p++, 0x00000000);                                     /* nop */
+    stl_p(p++, 0x08000205);                                     /* j 814 */
+    stl_p(p++, 0x00000000);                                     /* nop */
+    stl_p(p++, 0x01a00008);                                     /* jr t5 */
+    stl_p(p++, 0x01602021);                                     /* move a0,t3 */
     /* 0x83c YAMON print_count */
-    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
-    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
-    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
-    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
-    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
-    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
-    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
-    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
-    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    stl_p(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_p(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_p(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_p(p++, 0x00c06021);                                     /* move t4,a2 */
+    stl_p(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_p(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_p(p++, 0x00000000);                                     /* nop */
+    stl_p(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_p(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
+    stl_p(p++, 0x1580fffa);                                     /* bnez t4,84c */
+    stl_p(p++, 0x00000000);                                     /* nop */
+    stl_p(p++, 0x01a00008);                                     /* jr t5 */
+    stl_p(p++, 0x01602021);                                     /* move a0,t3 */
     /* 0x870 */
-    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
-    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
-    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
-    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x03e00008);                                     /* jr ra */
-    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
+    stl_p(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
+    stl_p(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
+    stl_p(p++, 0x91090005);                                     /* lbu t1,5(t0) */
+    stl_p(p++, 0x00000000);                                     /* nop */
+    stl_p(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
+    stl_p(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
+    stl_p(p++, 0x00000000);                                     /* nop */
+    stl_p(p++, 0x03e00008);                                     /* jr ra */
+    stl_p(p++, 0xa1040000);                                     /* sb a0,0(t0) */
 
 }
 
index 3a2a6c21c9bc92aa23f352b96f8f0b338d40958d..5a434f642d1886ff5b65f3e547043b2cc224fda3 100644 (file)
@@ -204,6 +204,13 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
     return size;
 }
 
+static void xilinx_ethlite_reset(DeviceState *dev)
+{
+    struct xlx_ethlite *s = XILINX_ETHLITE(dev);
+
+    s->rxbuf = 0;
+}
+
 static void eth_cleanup(NetClientState *nc)
 {
     struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
@@ -219,23 +226,25 @@ static NetClientInfo net_xilinx_ethlite_info = {
     .cleanup = eth_cleanup,
 };
 
-static int xilinx_ethlite_init(SysBusDevice *sbd)
+static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
 {
-    DeviceState *dev = DEVICE(sbd);
     struct xlx_ethlite *s = XILINX_ETHLITE(dev);
 
-    sysbus_init_irq(sbd, &s->irq);
-    s->rxbuf = 0;
-
-    memory_region_init_io(&s->mmio, OBJECT(s), &eth_ops, s,
-                          "xlnx.xps-ethernetlite", R_MAX * 4);
-    sysbus_init_mmio(sbd, &s->mmio);
-
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
                           object_get_typename(OBJECT(dev)), dev->id, s);
     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
-    return 0;
+}
+
+static void xilinx_ethlite_init(Object *obj)
+{
+    struct xlx_ethlite *s = XILINX_ETHLITE(obj);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+    memory_region_init_io(&s->mmio, obj, &eth_ops, s,
+                          "xlnx.xps-ethernetlite", R_MAX * 4);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 }
 
 static Property xilinx_ethlite_properties[] = {
@@ -248,9 +257,9 @@ static Property xilinx_ethlite_properties[] = {
 static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = xilinx_ethlite_init;
+    dc->realize = xilinx_ethlite_realize;
+    dc->reset = xilinx_ethlite_reset;
     dc->props = xilinx_ethlite_properties;
 }
 
@@ -258,6 +267,7 @@ static const TypeInfo xilinx_ethlite_info = {
     .name          = TYPE_XILINX_ETHLITE,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct xlx_ethlite),
+    .instance_init = xilinx_ethlite_init,
     .class_init    = xilinx_ethlite_class_init,
 };
 
index 252caefda7505fcd6eda9dd5583cfa37957002ee..1497008258addb180b18e6c78ffcedfa3cdd3434 100644 (file)
@@ -46,6 +46,16 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define APB_DPRINTF(fmt, ...)
 #endif
 
+/* debug IOMMU */
+//#define DEBUG_IOMMU
+
+#ifdef DEBUG_IOMMU
+#define IOMMU_DPRINTF(fmt, ...) \
+do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define IOMMU_DPRINTF(fmt, ...)
+#endif
+
 /*
  * Chipset docs:
  * PBM: "UltraSPARC IIi User's Manual",
@@ -70,6 +80,51 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define MAX_IVEC 0x40
 #define NO_IRQ_REQUEST (MAX_IVEC + 1)
 
+#define IOMMU_PAGE_SIZE_8K      (1ULL << 13)
+#define IOMMU_PAGE_MASK_8K      (~(IOMMU_PAGE_SIZE_8K - 1))
+#define IOMMU_PAGE_SIZE_64K     (1ULL << 16)
+#define IOMMU_PAGE_MASK_64K     (~(IOMMU_PAGE_SIZE_64K - 1))
+
+#define IOMMU_NREGS             3
+
+#define IOMMU_CTRL              0x0
+#define IOMMU_CTRL_TBW_SIZE     (1ULL << 2)
+#define IOMMU_CTRL_MMU_EN       (1ULL)
+
+#define IOMMU_CTRL_TSB_SHIFT    16
+
+#define IOMMU_BASE              0x8
+
+#define IOMMU_TTE_DATA_V        (1ULL << 63)
+#define IOMMU_TTE_DATA_SIZE     (1ULL << 61)
+#define IOMMU_TTE_DATA_W        (1ULL << 1)
+
+#define IOMMU_TTE_PHYS_MASK_8K  0x1ffffffe000
+#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000
+
+#define IOMMU_TSB_8K_OFFSET_MASK_8M    0x00000000007fe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_16M   0x0000000000ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_32M   0x0000000001ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_64M   0x0000000003ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_128M  0x0000000007ffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_256M  0x000000000fffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_512M  0x000000001fffe000ULL
+#define IOMMU_TSB_8K_OFFSET_MASK_1G    0x000000003fffe000ULL
+
+#define IOMMU_TSB_64K_OFFSET_MASK_64M  0x0000000003ff0000ULL
+#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL
+#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL
+#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL
+#define IOMMU_TSB_64K_OFFSET_MASK_1G   0x000000003fff0000ULL
+#define IOMMU_TSB_64K_OFFSET_MASK_2G   0x000000007fff0000ULL
+
+typedef struct IOMMUState {
+    AddressSpace iommu_as;
+    MemoryRegion iommu;
+
+    uint64_t regs[IOMMU_NREGS];
+} IOMMUState;
+
 #define TYPE_APB "pbm"
 
 #define APB_DEVICE(obj) \
@@ -83,7 +138,7 @@ typedef struct APBState {
     MemoryRegion pci_mmio;
     MemoryRegion pci_ioport;
     uint64_t pci_irq_in;
-    uint32_t iommu[4];
+    IOMMUState iommu;
     uint32_t pci_control[16];
     uint32_t pci_irq_map[8];
     uint32_t obio_irq_map[32];
@@ -141,10 +196,217 @@ static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
     s->irq_request = NO_IRQ_REQUEST;
 }
 
+static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
+{
+    IOMMUState *is = opaque;
+
+    return &is->iommu_as;
+}
+
+static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr)
+{
+    IOMMUState *is = container_of(iommu, IOMMUState, iommu);
+    hwaddr baseaddr, offset;
+    uint64_t tte;
+    uint32_t tsbsize;
+    IOMMUTLBEntry ret = {
+        .target_as = &address_space_memory,
+        .iova = 0,
+        .translated_addr = 0,
+        .addr_mask = ~(hwaddr)0,
+        .perm = IOMMU_NONE,
+    };
+
+    if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) {
+        /* IOMMU disabled, passthrough using standard 8K page */
+        ret.iova = addr & IOMMU_PAGE_MASK_8K;
+        ret.translated_addr = addr;
+        ret.addr_mask = IOMMU_PAGE_MASK_8K;
+        ret.perm = IOMMU_RW;
+
+        return ret;
+    }
+
+    baseaddr = is->regs[IOMMU_BASE >> 3];
+    tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7;
+
+    if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) {
+        /* 64K */
+        switch (tsbsize) {
+        case 0:
+            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13;
+            break;
+        case 1:
+            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13;
+            break;
+        case 2:
+            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13;
+            break;
+        case 3:
+            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13;
+            break;
+        case 4:
+            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13;
+            break;
+        case 5:
+            offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13;
+            break;
+        default:
+            /* Not implemented, error */
+            return ret;
+        }
+    } else {
+        /* 8K */
+        switch (tsbsize) {
+        case 0:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10;
+            break;
+        case 1:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10;
+            break;
+        case 2:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10;
+            break;
+        case 3:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10;
+            break;
+        case 4:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10;
+            break;
+        case 5:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10;
+            break;
+        case 6:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10;
+            break;
+        case 7:
+            offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10;
+            break;
+        }
+    }
+
+    tte = ldq_be_phys(&address_space_memory, baseaddr + offset);
+
+    if (!(tte & IOMMU_TTE_DATA_V)) {
+        /* Invalid mapping */
+        return ret;
+    }
+
+    if (tte & IOMMU_TTE_DATA_W) {
+        /* Writeable */
+        ret.perm = IOMMU_RW;
+    } else {
+        ret.perm = IOMMU_RO;
+    }
+
+    /* Extract phys */
+    if (tte & IOMMU_TTE_DATA_SIZE) {
+        /* 64K */
+        ret.iova = addr & IOMMU_PAGE_MASK_64K;
+        ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K;
+        ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1);
+    } else {
+        /* 8K */
+        ret.iova = addr & IOMMU_PAGE_MASK_8K;
+        ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K;
+        ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1);
+    }
+
+    return ret;
+}
+
+static MemoryRegionIOMMUOps pbm_iommu_ops = {
+    .translate = pbm_translate_iommu,
+};
+
+static void iommu_config_write(void *opaque, hwaddr addr,
+                               uint64_t val, unsigned size)
+{
+    IOMMUState *is = opaque;
+
+    IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64
+                  " size: %d\n", addr, val, size);
+
+    switch (addr) {
+    case IOMMU_CTRL:
+        if (size == 4) {
+            is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL;
+            is->regs[IOMMU_CTRL >> 3] |= val << 32;
+        } else {
+            is->regs[IOMMU_CTRL] = val;
+        }
+        break;
+    case IOMMU_CTRL + 0x4:
+        is->regs[IOMMU_CTRL >> 3] &= 0xffffffff00000000ULL;
+        is->regs[IOMMU_CTRL >> 3] |= val & 0xffffffffULL;
+        break;
+    case IOMMU_BASE:
+        if (size == 4) {
+            is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL;
+            is->regs[IOMMU_BASE >> 3] |= val << 32;
+        } else {
+            is->regs[IOMMU_BASE] = val;
+        }
+        break;
+    case IOMMU_BASE + 0x4:
+        is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL;
+        is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL;
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP,
+                  "apb iommu: Unimplemented register write "
+                  "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
+                  addr, size, val);
+        break;
+    }
+}
+
+static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size)
+{
+    IOMMUState *is = opaque;
+    uint64_t val;
+
+    switch (addr) {
+    case IOMMU_CTRL:
+        if (size == 4) {
+            val = is->regs[IOMMU_CTRL >> 3] >> 32;
+        } else {
+            val = is->regs[IOMMU_CTRL >> 3];
+        }
+        break;
+    case IOMMU_CTRL + 0x4:
+        val = is->regs[IOMMU_CTRL >> 3] & 0xffffffffULL;
+        break;
+    case IOMMU_BASE:
+        if (size == 4) {
+            val = is->regs[IOMMU_BASE >> 3] >> 32;
+        } else {
+            val = is->regs[IOMMU_BASE >> 3];
+        }
+        break;
+    case IOMMU_BASE + 0x4:
+        val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL;
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP,
+                      "apb iommu: Unimplemented register read "
+                      "reg 0x%" HWADDR_PRIx " size 0x%x\n",
+                      addr, size);
+        val = 0;
+        break;
+    }
+
+    IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64
+                  " size: %d\n", addr, val, size);
+
+    return val;
+}
+
 static void apb_config_writel (void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
 {
     APBState *s = opaque;
+    IOMMUState *is = &s->iommu;
 
     APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
 
@@ -152,10 +414,8 @@ static void apb_config_writel (void *opaque, hwaddr addr,
     case 0x30 ... 0x4f: /* DMA error registers */
         /* XXX: not implemented yet */
         break;
-    case 0x200 ... 0x20b: /* IOMMU */
-        s->iommu[(addr & 0xf) >> 2] = val;
-        break;
-    case 0x20c ... 0x3ff: /* IOMMU flush */
+    case 0x200 ... 0x217: /* IOMMU */
+        iommu_config_write(is, (addr & 0xf), val, size);
         break;
     case 0xc00 ... 0xc3f: /* PCI interrupt control */
         if (addr & 4) {
@@ -228,6 +488,7 @@ static uint64_t apb_config_readl (void *opaque,
                                   hwaddr addr, unsigned size)
 {
     APBState *s = opaque;
+    IOMMUState *is = &s->iommu;
     uint32_t val;
 
     switch (addr & 0xffff) {
@@ -235,11 +496,8 @@ static uint64_t apb_config_readl (void *opaque,
         val = 0;
         /* XXX: not implemented yet */
         break;
-    case 0x200 ... 0x20b: /* IOMMU */
-        val = s->iommu[(addr & 0xf) >> 2];
-        break;
-    case 0x20c ... 0x3ff: /* IOMMU flush */
-        val = 0;
+    case 0x200 ... 0x217: /* IOMMU */
+        val = iommu_config_read(is, (addr & 0xf), size);
         break;
     case 0xc00 ... 0xc3f: /* PCI interrupt control */
         if (addr & 4) {
@@ -390,6 +648,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
     SysBusDevice *s;
     PCIHostState *phb;
     APBState *d;
+    IOMMUState *is;
     PCIDevice *pci_dev;
     PCIBridge *br;
 
@@ -420,6 +679,15 @@ PCIBus *pci_apb_init(hwaddr special_base,
 
     pci_create_simple(phb->bus, 0, "pbm-pci");
 
+    /* APB IOMMU */
+    is = &d->iommu;
+    memset(is, 0, sizeof(IOMMUState));
+
+    memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
+                             "iommu-apb", UINT64_MAX);
+    address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
+    pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
+
     /* APB secondary busses */
     pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
                                    "pbm-bridge");
index 8b8cc4e294f21d009b052615e977fdce722bb375..aa48b1c82fc6ac2f3247a3337e9d2b88b8575fdc 100644 (file)
@@ -47,10 +47,6 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
     sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
     sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
 
-    if (pcie_host_init(PCIE_HOST_BRIDGE(s)) < 0) {
-        error_setg(errp, "failed to initialize pcie host");
-        return;
-    }
     pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
                            s->mch.pci_address_space, s->mch.address_space_io,
                            0, TYPE_PCIE_BUS);
index c6e1b573e1681c4510f0f1fd2e17545cb40183a9..7c88a1d09186715285e3045d44ff220df7d533df 100644 (file)
@@ -83,11 +83,11 @@ static const MemoryRegionOps pcie_mmcfg_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-int pcie_host_init(PCIExpressHost *e)
+static void pcie_host_init(Object *obj)
 {
-    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
+    PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
 
-    return 0;
+    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
 }
 
 void pcie_host_mmcfg_unmap(PCIExpressHost *e)
@@ -128,6 +128,7 @@ static const TypeInfo pcie_host_type_info = {
     .parent = TYPE_PCI_HOST_BRIDGE,
     .abstract = true,
     .instance_size = sizeof(PCIExpressHost),
+    .instance_init = pcie_host_init,
 };
 
 static void pcie_host_register_types(void)
index 3983a5b46402686d78f0e2291b2233d4b0366f81..668bafa72a612e40ae7a0c767882d834583f0214 100644 (file)
@@ -164,8 +164,8 @@ static void vhost_scsi_set_config(VirtIODevice *vdev,
     VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
 
-    if ((uint32_t) ldl_raw(&scsiconf->sense_size) != vs->sense_size ||
-        (uint32_t) ldl_raw(&scsiconf->cdb_size) != vs->cdb_size) {
+    if ((uint32_t) ldl_p(&scsiconf->sense_size) != vs->sense_size ||
+        (uint32_t) ldl_p(&scsiconf->cdb_size) != vs->cdb_size) {
         error_report("vhost-scsi does not support changing the sense data and CDB sizes");
         exit(1);
     }
index 14261fb1a709ee6d031bf4c09a37f910229fd964..b39880a9cdc3277790ae656bad8c0629c49023be 100644 (file)
@@ -425,16 +425,16 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
     VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
     VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(vdev);
 
-    stl_raw(&scsiconf->num_queues, s->conf.num_queues);
-    stl_raw(&scsiconf->seg_max, 128 - 2);
-    stl_raw(&scsiconf->max_sectors, s->conf.max_sectors);
-    stl_raw(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
-    stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
-    stl_raw(&scsiconf->sense_size, s->sense_size);
-    stl_raw(&scsiconf->cdb_size, s->cdb_size);
-    stw_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
-    stw_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
-    stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
+    stl_p(&scsiconf->num_queues, s->conf.num_queues);
+    stl_p(&scsiconf->seg_max, 128 - 2);
+    stl_p(&scsiconf->max_sectors, s->conf.max_sectors);
+    stl_p(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
+    stl_p(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
+    stl_p(&scsiconf->sense_size, s->sense_size);
+    stl_p(&scsiconf->cdb_size, s->cdb_size);
+    stw_p(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
+    stw_p(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
+    stl_p(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
 }
 
 static void virtio_scsi_set_config(VirtIODevice *vdev,
@@ -443,14 +443,14 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
     VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
 
-    if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
-        (uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
+    if ((uint32_t) ldl_p(&scsiconf->sense_size) >= 65536 ||
+        (uint32_t) ldl_p(&scsiconf->cdb_size) >= 256) {
         error_report("bad data written to virtio-scsi configuration space");
         exit(1);
     }
 
-    vs->sense_size = ldl_raw(&scsiconf->sense_size);
-    vs->cdb_size = ldl_raw(&scsiconf->cdb_size);
+    vs->sense_size = ldl_p(&scsiconf->sense_size);
+    vs->cdb_size = ldl_p(&scsiconf->cdb_size);
 }
 
 static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
index 4e793c2760569bd5ce12fa751d5dc9c22aba32ac..67e3663bfdd60529b7305425080002ccc2030117 100644 (file)
@@ -543,14 +543,14 @@ static void tcx_init(hwaddr addr, int vram_size, int width,
     s = SYS_BUS_DEVICE(dev);
     /* FCode ROM */
     sysbus_mmio_map(s, 0, addr);
-    /* 8-bit plane */
-    sysbus_mmio_map(s, 1, addr + 0x00800000ULL);
     /* DAC */
-    sysbus_mmio_map(s, 2, addr + 0x00200000ULL);
+    sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
     /* TEC (dummy) */
-    sysbus_mmio_map(s, 3, addr + 0x00700000ULL);
+    sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
     /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
-    sysbus_mmio_map(s, 4, addr + 0x00301000ULL);
+    sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
+    /* 8-bit plane */
+    sysbus_mmio_map(s, 4, addr + 0x00800000ULL);
     if (depth == 24) {
         /* 24-bit plane */
         sysbus_mmio_map(s, 5, addr + 0x02000000ULL);
index 3ff1da9cafb5bd50874515bf320ef281b00901df..cdb33551740676f5c131a824ab9bfb02283eb5ca 100644 (file)
@@ -204,14 +204,11 @@ static void timer_hit(void *opaque)
     timer_update_irq(t);
 }
 
-static int xilinx_timer_init(SysBusDevice *dev)
+static void xilinx_timer_realize(DeviceState *dev, Error **errp)
 {
     struct timerblock *t = XILINX_TIMER(dev);
     unsigned int i;
 
-    /* All timers share a single irq line.  */
-    sysbus_init_irq(dev, &t->irq);
-
     /* Init all the ptimers.  */
     t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t));
     for (i = 0; i < num_timers(t); i++) {
@@ -226,8 +223,15 @@ static int xilinx_timer_init(SysBusDevice *dev)
 
     memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
                           R_MAX * 4 * num_timers(t));
-    sysbus_init_mmio(dev, &t->mmio);
-    return 0;
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio);
+}
+
+static void xilinx_timer_init(Object *obj)
+{
+    struct timerblock *t = XILINX_TIMER(obj);
+
+    /* All timers share a single irq line.  */
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq);
 }
 
 static Property xilinx_timer_properties[] = {
@@ -240,9 +244,8 @@ static Property xilinx_timer_properties[] = {
 static void xilinx_timer_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = xilinx_timer_init;
+    dc->realize = xilinx_timer_realize;
     dc->props = xilinx_timer_properties;
 }
 
@@ -250,6 +253,7 @@ static const TypeInfo xilinx_timer_info = {
     .name          = TYPE_XILINX_TIMER,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct timerblock),
+    .instance_init = xilinx_timer_init,
     .class_init    = xilinx_timer_class_init,
 };
 
index bf2b588b24bbc4cd2c296314110d175a39437ebc..22cd52edeecc95b814053c16c9aebd00404cb3f1 100644 (file)
@@ -112,11 +112,6 @@ static void balloon_stats_get_all(Object *obj, struct Visitor *v,
     VirtIOBalloon *s = opaque;
     int i;
 
-    if (!s->stats_last_update) {
-        error_setg(errp, "guest hasn't updated any stats yet");
-        return;
-    }
-
     visit_start_struct(v, NULL, "guest-stats", name, 0, &err);
     if (err) {
         goto out;
@@ -378,6 +373,8 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
     s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
     s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
 
+    reset_stats(s);
+
     register_savevm(dev, "virtio-balloon", -1, 1,
                     virtio_balloon_save, virtio_balloon_load, s);
 
index 9cab592dc5febb7b8cd08ad07fc8d3a690c98671..e8363d72485422614ac02558bb773a9a88a80c00 100644 (file)
@@ -198,127 +198,8 @@ extern unsigned long reserved_va;
 #define RESERVED_VA 0ul
 #endif
 
-/* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
-#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
-
-#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
-#define h2g_valid(x) 1
-#else
-#define h2g_valid(x) ({ \
-    unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
-    (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
-    (!RESERVED_VA || (__guest < RESERVED_VA)); \
-})
 #endif
 
-#define h2g_nocheck(x) ({ \
-    unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
-    (abi_ulong)__ret; \
-})
-
-#define h2g(x) ({ \
-    /* Check if given address fits target address space */ \
-    assert(h2g_valid(x)); \
-    h2g_nocheck(x); \
-})
-
-#define saddr(x) g2h(x)
-#define laddr(x) g2h(x)
-
-#else /* !CONFIG_USER_ONLY */
-/* NOTE: we use double casts if pointers and target_ulong have
-   different sizes */
-#define saddr(x) (uint8_t *)(intptr_t)(x)
-#define laddr(x) (uint8_t *)(intptr_t)(x)
-#endif
-
-#define ldub_raw(p) ldub_p(laddr((p)))
-#define ldsb_raw(p) ldsb_p(laddr((p)))
-#define lduw_raw(p) lduw_p(laddr((p)))
-#define ldsw_raw(p) ldsw_p(laddr((p)))
-#define ldl_raw(p) ldl_p(laddr((p)))
-#define ldq_raw(p) ldq_p(laddr((p)))
-#define ldfl_raw(p) ldfl_p(laddr((p)))
-#define ldfq_raw(p) ldfq_p(laddr((p)))
-#define stb_raw(p, v) stb_p(saddr((p)), v)
-#define stw_raw(p, v) stw_p(saddr((p)), v)
-#define stl_raw(p, v) stl_p(saddr((p)), v)
-#define stq_raw(p, v) stq_p(saddr((p)), v)
-#define stfl_raw(p, v) stfl_p(saddr((p)), v)
-#define stfq_raw(p, v) stfq_p(saddr((p)), v)
-
-
-#if defined(CONFIG_USER_ONLY)
-
-/* if user mode, no other memory access functions */
-#define ldub(p) ldub_raw(p)
-#define ldsb(p) ldsb_raw(p)
-#define lduw(p) lduw_raw(p)
-#define ldsw(p) ldsw_raw(p)
-#define ldl(p) ldl_raw(p)
-#define ldq(p) ldq_raw(p)
-#define ldfl(p) ldfl_raw(p)
-#define ldfq(p) ldfq_raw(p)
-#define stb(p, v) stb_raw(p, v)
-#define stw(p, v) stw_raw(p, v)
-#define stl(p, v) stl_raw(p, v)
-#define stq(p, v) stq_raw(p, v)
-#define stfl(p, v) stfl_raw(p, v)
-#define stfq(p, v) stfq_raw(p, v)
-
-#define cpu_ldub_code(env1, p) ldub_raw(p)
-#define cpu_ldsb_code(env1, p) ldsb_raw(p)
-#define cpu_lduw_code(env1, p) lduw_raw(p)
-#define cpu_ldsw_code(env1, p) ldsw_raw(p)
-#define cpu_ldl_code(env1, p) ldl_raw(p)
-#define cpu_ldq_code(env1, p) ldq_raw(p)
-
-#define cpu_ldub_data(env, addr) ldub_raw(addr)
-#define cpu_lduw_data(env, addr) lduw_raw(addr)
-#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
-#define cpu_ldl_data(env, addr) ldl_raw(addr)
-#define cpu_ldq_data(env, addr) ldq_raw(addr)
-
-#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
-#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
-#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
-#define cpu_stq_data(env, addr, data) stq_raw(addr, data)
-
-#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
-#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
-#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
-#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
-#define cpu_ldq_kernel(env, addr) ldq_raw(addr)
-
-#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
-#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
-#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
-#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
-
-#define ldub_kernel(p) ldub_raw(p)
-#define ldsb_kernel(p) ldsb_raw(p)
-#define lduw_kernel(p) lduw_raw(p)
-#define ldsw_kernel(p) ldsw_raw(p)
-#define ldl_kernel(p) ldl_raw(p)
-#define ldq_kernel(p) ldq_raw(p)
-#define ldfl_kernel(p) ldfl_raw(p)
-#define ldfq_kernel(p) ldfq_raw(p)
-#define stb_kernel(p, v) stb_raw(p, v)
-#define stw_kernel(p, v) stw_raw(p, v)
-#define stl_kernel(p, v) stl_raw(p, v)
-#define stq_kernel(p, v) stq_raw(p, v)
-#define stfl_kernel(p, v) stfl_raw(p, v)
-#define stfq_kernel(p, vt) stfq_raw(p, v)
-
-#define cpu_ldub_data(env, addr) ldub_raw(addr)
-#define cpu_lduw_data(env, addr) lduw_raw(addr)
-#define cpu_ldl_data(env, addr) ldl_raw(addr)
-
-#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
-#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
-#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
-#endif /* defined(CONFIG_USER_ONLY) */
-
 /* page related stuff */
 
 #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
new file mode 100644 (file)
index 0000000..e5550e7
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ *  Software MMU support
+ *
+ * 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/>.
+ *
+ */
+
+/*
+ * Generate inline load/store functions for all MMU modes (typically
+ * at least _user and _kernel) as well as _data versions, for all data
+ * sizes.
+ *
+ * Used by target op helpers.
+ *
+ * MMU mode suffixes are defined in target cpu.h.
+ */
+#ifndef CPU_LDST_H
+#define CPU_LDST_H
+
+#if defined(CONFIG_USER_ONLY)
+/* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
+#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
+
+#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
+#define h2g_valid(x) 1
+#else
+#define h2g_valid(x) ({ \
+    unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
+    (__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
+    (!RESERVED_VA || (__guest < RESERVED_VA)); \
+})
+#endif
+
+#define h2g_nocheck(x) ({ \
+    unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
+    (abi_ulong)__ret; \
+})
+
+#define h2g(x) ({ \
+    /* Check if given address fits target address space */ \
+    assert(h2g_valid(x)); \
+    h2g_nocheck(x); \
+})
+
+#define saddr(x) g2h(x)
+#define laddr(x) g2h(x)
+
+#else /* !CONFIG_USER_ONLY */
+/* NOTE: we use double casts if pointers and target_ulong have
+   different sizes */
+#define saddr(x) (uint8_t *)(intptr_t)(x)
+#define laddr(x) (uint8_t *)(intptr_t)(x)
+#endif
+
+#define ldub_raw(p) ldub_p(laddr((p)))
+#define ldsb_raw(p) ldsb_p(laddr((p)))
+#define lduw_raw(p) lduw_p(laddr((p)))
+#define ldsw_raw(p) ldsw_p(laddr((p)))
+#define ldl_raw(p) ldl_p(laddr((p)))
+#define ldq_raw(p) ldq_p(laddr((p)))
+#define ldfl_raw(p) ldfl_p(laddr((p)))
+#define ldfq_raw(p) ldfq_p(laddr((p)))
+#define stb_raw(p, v) stb_p(saddr((p)), v)
+#define stw_raw(p, v) stw_p(saddr((p)), v)
+#define stl_raw(p, v) stl_p(saddr((p)), v)
+#define stq_raw(p, v) stq_p(saddr((p)), v)
+#define stfl_raw(p, v) stfl_p(saddr((p)), v)
+#define stfq_raw(p, v) stfq_p(saddr((p)), v)
+
+
+#if defined(CONFIG_USER_ONLY)
+
+/* if user mode, no other memory access functions */
+#define ldub(p) ldub_raw(p)
+#define ldsb(p) ldsb_raw(p)
+#define lduw(p) lduw_raw(p)
+#define ldsw(p) ldsw_raw(p)
+#define ldl(p) ldl_raw(p)
+#define ldq(p) ldq_raw(p)
+#define ldfl(p) ldfl_raw(p)
+#define ldfq(p) ldfq_raw(p)
+#define stb(p, v) stb_raw(p, v)
+#define stw(p, v) stw_raw(p, v)
+#define stl(p, v) stl_raw(p, v)
+#define stq(p, v) stq_raw(p, v)
+#define stfl(p, v) stfl_raw(p, v)
+#define stfq(p, v) stfq_raw(p, v)
+
+#define cpu_ldub_code(env1, p) ldub_raw(p)
+#define cpu_ldsb_code(env1, p) ldsb_raw(p)
+#define cpu_lduw_code(env1, p) lduw_raw(p)
+#define cpu_ldsw_code(env1, p) ldsw_raw(p)
+#define cpu_ldl_code(env1, p) ldl_raw(p)
+#define cpu_ldq_code(env1, p) ldq_raw(p)
+
+#define cpu_ldub_data(env, addr) ldub_raw(addr)
+#define cpu_lduw_data(env, addr) lduw_raw(addr)
+#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
+#define cpu_ldl_data(env, addr) ldl_raw(addr)
+#define cpu_ldq_data(env, addr) ldq_raw(addr)
+
+#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
+#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
+#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
+#define cpu_stq_data(env, addr, data) stq_raw(addr, data)
+
+#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
+#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
+#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
+#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
+#define cpu_ldq_kernel(env, addr) ldq_raw(addr)
+
+#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
+#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
+#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
+#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
+
+#define ldub_kernel(p) ldub_raw(p)
+#define ldsb_kernel(p) ldsb_raw(p)
+#define lduw_kernel(p) lduw_raw(p)
+#define ldsw_kernel(p) ldsw_raw(p)
+#define ldl_kernel(p) ldl_raw(p)
+#define ldq_kernel(p) ldq_raw(p)
+#define ldfl_kernel(p) ldfl_raw(p)
+#define ldfq_kernel(p) ldfq_raw(p)
+#define stb_kernel(p, v) stb_raw(p, v)
+#define stw_kernel(p, v) stw_raw(p, v)
+#define stl_kernel(p, v) stl_raw(p, v)
+#define stq_kernel(p, v) stq_raw(p, v)
+#define stfl_kernel(p, v) stfl_raw(p, v)
+#define stfq_kernel(p, vt) stfq_raw(p, v)
+
+#define cpu_ldub_data(env, addr) ldub_raw(addr)
+#define cpu_lduw_data(env, addr) lduw_raw(addr)
+#define cpu_ldl_data(env, addr) ldl_raw(addr)
+
+#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
+#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
+#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
+
+#else
+
+/* XXX: find something cleaner.
+ * Furthermore, this is false for 64 bits targets
+ */
+#define ldul_user       ldl_user
+#define ldul_kernel     ldl_kernel
+#define ldul_hypv       ldl_hypv
+#define ldul_executive  ldl_executive
+#define ldul_supervisor ldl_supervisor
+
+/* The memory helpers for tcg-generated code need tcg_target_long etc.  */
+#include "tcg.h"
+
+uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+
+void helper_stb_mmu(CPUArchState *env, target_ulong addr,
+                    uint8_t val, int mmu_idx);
+void helper_stw_mmu(CPUArchState *env, target_ulong addr,
+                    uint16_t val, int mmu_idx);
+void helper_stl_mmu(CPUArchState *env, target_ulong addr,
+                    uint32_t val, int mmu_idx);
+void helper_stq_mmu(CPUArchState *env, target_ulong addr,
+                    uint64_t val, int mmu_idx);
+
+uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
+
+#define CPU_MMU_INDEX 0
+#define MEMSUFFIX MMU_MODE0_SUFFIX
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+
+#define CPU_MMU_INDEX 1
+#define MEMSUFFIX MMU_MODE1_SUFFIX
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+
+#if (NB_MMU_MODES >= 3)
+
+#define CPU_MMU_INDEX 2
+#define MEMSUFFIX MMU_MODE2_SUFFIX
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 3) */
+
+#if (NB_MMU_MODES >= 4)
+
+#define CPU_MMU_INDEX 3
+#define MEMSUFFIX MMU_MODE3_SUFFIX
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 4) */
+
+#if (NB_MMU_MODES >= 5)
+
+#define CPU_MMU_INDEX 4
+#define MEMSUFFIX MMU_MODE4_SUFFIX
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 5) */
+
+#if (NB_MMU_MODES >= 6)
+
+#define CPU_MMU_INDEX 5
+#define MEMSUFFIX MMU_MODE5_SUFFIX
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 6) */
+
+#if (NB_MMU_MODES > 6)
+#error "NB_MMU_MODES > 6 is not supported for now"
+#endif /* (NB_MMU_MODES > 6) */
+
+/* these access are slower, they must be as rare as possible */
+#define CPU_MMU_INDEX (cpu_mmu_index(env))
+#define MEMSUFFIX _data
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+
+#define ldub(p) ldub_data(p)
+#define ldsb(p) ldsb_data(p)
+#define lduw(p) lduw_data(p)
+#define ldsw(p) ldsw_data(p)
+#define ldl(p) ldl_data(p)
+#define ldq(p) ldq_data(p)
+
+#define stb(p, v) stb_data(p, v)
+#define stw(p, v) stw_data(p, v)
+#define stl(p, v) stl_data(p, v)
+#define stq(p, v) stq_data(p, v)
+
+#define CPU_MMU_INDEX (cpu_mmu_index(env))
+#define MEMSUFFIX _code
+#define SOFTMMU_CODE_ACCESS
+
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+#undef SOFTMMU_CODE_ACCESS
+
+/**
+ * tlb_vaddr_to_host:
+ * @env: CPUArchState
+ * @addr: guest virtual address to look up
+ * @access_type: 0 for read, 1 for write, 2 for execute
+ * @mmu_idx: MMU index to use for lookup
+ *
+ * Look up the specified guest virtual index in the TCG softmmu TLB.
+ * If the TLB contains a host virtual address suitable for direct RAM
+ * access, then return it. Otherwise (TLB miss, TLB entry is for an
+ * I/O access, etc) return NULL.
+ *
+ * This is the equivalent of the initial fast-path code used by
+ * TCG backends for guest load and store accesses.
+ */
+static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
+                                      int access_type, int mmu_idx)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
+    target_ulong tlb_addr;
+    uintptr_t haddr;
+
+    switch (access_type) {
+    case 0:
+        tlb_addr = tlbentry->addr_read;
+        break;
+    case 1:
+        tlb_addr = tlbentry->addr_write;
+        break;
+    case 2:
+        tlb_addr = tlbentry->addr_code;
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    if ((addr & TARGET_PAGE_MASK)
+        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+        /* TLB entry is for a different page */
+        return NULL;
+    }
+
+    if (tlb_addr & ~TARGET_PAGE_MASK) {
+        /* IO access */
+        return NULL;
+    }
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+    return (void *)haddr;
+}
+
+#endif /* defined(CONFIG_USER_ONLY) */
+
+#endif /* CPU_LDST_H */
diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h
new file mode 100644 (file)
index 0000000..006093a
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ *  Software MMU support
+ *
+ * Generate inline load/store functions for one MMU mode and data
+ * size.
+ *
+ * Generate a store function as well as signed and unsigned loads. For
+ * 32 and 64 bit cases, also generate floating point functions with
+ * the same size.
+ *
+ * Not used directly but included from cpu_ldst.h.
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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/>.
+ */
+#if DATA_SIZE == 8
+#define SUFFIX q
+#define USUFFIX q
+#define DATA_TYPE uint64_t
+#elif DATA_SIZE == 4
+#define SUFFIX l
+#define USUFFIX l
+#define DATA_TYPE uint32_t
+#elif DATA_SIZE == 2
+#define SUFFIX w
+#define USUFFIX uw
+#define DATA_TYPE uint16_t
+#define DATA_STYPE int16_t
+#elif DATA_SIZE == 1
+#define SUFFIX b
+#define USUFFIX ub
+#define DATA_TYPE uint8_t
+#define DATA_STYPE int8_t
+#else
+#error unsupported data size
+#endif
+
+#if DATA_SIZE == 8
+#define RES_TYPE uint64_t
+#else
+#define RES_TYPE uint32_t
+#endif
+
+#ifdef SOFTMMU_CODE_ACCESS
+#define ADDR_READ addr_code
+#define MMUSUFFIX _cmmu
+#else
+#define ADDR_READ addr_read
+#define MMUSUFFIX _mmu
+#endif
+
+/* generic load/store macros */
+
+static inline RES_TYPE
+glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
+{
+    int page_index;
+    RES_TYPE res;
+    target_ulong addr;
+    int mmu_idx;
+
+    addr = ptr;
+    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    mmu_idx = CPU_MMU_INDEX;
+    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
+                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
+        res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx);
+    } else {
+        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+        res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
+    }
+    return res;
+}
+
+#if DATA_SIZE <= 2
+static inline int
+glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
+{
+    int res, page_index;
+    target_ulong addr;
+    int mmu_idx;
+
+    addr = ptr;
+    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    mmu_idx = CPU_MMU_INDEX;
+    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
+                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
+        res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX),
+                               MMUSUFFIX)(env, addr, mmu_idx);
+    } else {
+        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+        res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
+    }
+    return res;
+}
+#endif
+
+#ifndef SOFTMMU_CODE_ACCESS
+
+/* generic store macro */
+
+static inline void
+glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
+                                      RES_TYPE v)
+{
+    int page_index;
+    target_ulong addr;
+    int mmu_idx;
+
+    addr = ptr;
+    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    mmu_idx = CPU_MMU_INDEX;
+    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
+                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
+        glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx);
+    } else {
+        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+        glue(glue(st, SUFFIX), _raw)(hostaddr, v);
+    }
+}
+
+
+
+#if DATA_SIZE == 8
+static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env,
+                                                target_ulong ptr)
+{
+    union {
+        float64 d;
+        uint64_t i;
+    } u;
+    u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr);
+    return u.d;
+}
+
+static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env,
+                                             target_ulong ptr, float64 v)
+{
+    union {
+        float64 d;
+        uint64_t i;
+    } u;
+    u.d = v;
+    glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i);
+}
+#endif /* DATA_SIZE == 8 */
+
+#if DATA_SIZE == 4
+static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env,
+                                                target_ulong ptr)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr);
+    return u.f;
+}
+
+static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
+                                             target_ulong ptr, float32 v)
+{
+    union {
+        float32 f;
+        uint32_t i;
+    } u;
+    u.f = v;
+    glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i);
+}
+#endif /* DATA_SIZE == 4 */
+
+#endif /* !SOFTMMU_CODE_ACCESS */
+
+#undef RES_TYPE
+#undef DATA_TYPE
+#undef DATA_STYPE
+#undef SUFFIX
+#undef USUFFIX
+#undef DATA_SIZE
+#undef MMUSUFFIX
+#undef ADDR_READ
index c964ca4f0b2fab1d5dfdd352d5f53799cddf2a82..3d62d9c464c503f4c8b14c7405dd3ad38943c740 100644 (file)
@@ -344,29 +344,6 @@ bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
 void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx,
               uintptr_t retaddr);
 
-uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-
-#define ACCESS_TYPE (NB_MMU_MODES + 1)
-#define MEMSUFFIX _code
-
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-
 #endif
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/include/exec/softmmu_exec.h b/include/exec/softmmu_exec.h
deleted file mode 100644 (file)
index 470db20..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- *  Software MMU support
- *
- * Generate inline load/store functions for all MMU modes (typically
- * at least _user and _kernel) as well as _data versions, for all data
- * sizes.
- *
- * Used by target op helpers.
- *
- * MMU mode suffixes are defined in target cpu.h.
- */
-
-/* XXX: find something cleaner.
- * Furthermore, this is false for 64 bits targets
- */
-#define ldul_user       ldl_user
-#define ldul_kernel     ldl_kernel
-#define ldul_hypv       ldl_hypv
-#define ldul_executive  ldl_executive
-#define ldul_supervisor ldl_supervisor
-
-/* The memory helpers for tcg-generated code need tcg_target_long etc.  */
-#include "tcg.h"
-
-#define ACCESS_TYPE 0
-#define MEMSUFFIX MMU_MODE0_SUFFIX
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-
-#define ACCESS_TYPE 1
-#define MEMSUFFIX MMU_MODE1_SUFFIX
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-
-#if (NB_MMU_MODES >= 3)
-
-#define ACCESS_TYPE 2
-#define MEMSUFFIX MMU_MODE2_SUFFIX
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-#endif /* (NB_MMU_MODES >= 3) */
-
-#if (NB_MMU_MODES >= 4)
-
-#define ACCESS_TYPE 3
-#define MEMSUFFIX MMU_MODE3_SUFFIX
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-#endif /* (NB_MMU_MODES >= 4) */
-
-#if (NB_MMU_MODES >= 5)
-
-#define ACCESS_TYPE 4
-#define MEMSUFFIX MMU_MODE4_SUFFIX
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-#endif /* (NB_MMU_MODES >= 5) */
-
-#if (NB_MMU_MODES >= 6)
-
-#define ACCESS_TYPE 5
-#define MEMSUFFIX MMU_MODE5_SUFFIX
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-#endif /* (NB_MMU_MODES >= 6) */
-
-#if (NB_MMU_MODES > 6)
-#error "NB_MMU_MODES > 6 is not supported for now"
-#endif /* (NB_MMU_MODES > 6) */
-
-/* these access are slower, they must be as rare as possible */
-#define ACCESS_TYPE (NB_MMU_MODES)
-#define MEMSUFFIX _data
-#define DATA_SIZE 1
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 2
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 4
-#include "exec/softmmu_header.h"
-
-#define DATA_SIZE 8
-#include "exec/softmmu_header.h"
-#undef ACCESS_TYPE
-#undef MEMSUFFIX
-
-#define ldub(p) ldub_data(p)
-#define ldsb(p) ldsb_data(p)
-#define lduw(p) lduw_data(p)
-#define ldsw(p) ldsw_data(p)
-#define ldl(p) ldl_data(p)
-#define ldq(p) ldq_data(p)
-
-#define stb(p, v) stb_data(p, v)
-#define stw(p, v) stw_data(p, v)
-#define stl(p, v) stl_data(p, v)
-#define stq(p, v) stq_data(p, v)
-
-/**
- * tlb_vaddr_to_host:
- * @env: CPUArchState
- * @addr: guest virtual address to look up
- * @access_type: 0 for read, 1 for write, 2 for execute
- * @mmu_idx: MMU index to use for lookup
- *
- * Look up the specified guest virtual index in the TCG softmmu TLB.
- * If the TLB contains a host virtual address suitable for direct RAM
- * access, then return it. Otherwise (TLB miss, TLB entry is for an
- * I/O access, etc) return NULL.
- *
- * This is the equivalent of the initial fast-path code used by
- * TCG backends for guest load and store accesses.
- */
-static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
-                                      int access_type, int mmu_idx)
-{
-    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
-    target_ulong tlb_addr;
-    uintptr_t haddr;
-
-    switch (access_type) {
-    case 0:
-        tlb_addr = tlbentry->addr_read;
-        break;
-    case 1:
-        tlb_addr = tlbentry->addr_write;
-        break;
-    case 2:
-        tlb_addr = tlbentry->addr_code;
-        break;
-    default:
-        g_assert_not_reached();
-    }
-
-    if ((addr & TARGET_PAGE_MASK)
-        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-        /* TLB entry is for a different page */
-        return NULL;
-    }
-
-    if (tlb_addr & ~TARGET_PAGE_MASK) {
-        /* IO access */
-        return NULL;
-    }
-
-    haddr = addr + env->tlb_table[mmu_idx][index].addend;
-    return (void *)haddr;
-}
diff --git a/include/exec/softmmu_header.h b/include/exec/softmmu_header.h
deleted file mode 100644 (file)
index d8d9c81..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- *  Software MMU support
- *
- * Generate inline load/store functions for one MMU mode and data
- * size.
- *
- * Generate a store function as well as signed and unsigned loads. For
- * 32 and 64 bit cases, also generate floating point functions with
- * the same size.
- *
- * Not used directly but included from softmmu_exec.h and exec-all.h.
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- * 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/>.
- */
-#if DATA_SIZE == 8
-#define SUFFIX q
-#define USUFFIX q
-#define DATA_TYPE uint64_t
-#elif DATA_SIZE == 4
-#define SUFFIX l
-#define USUFFIX l
-#define DATA_TYPE uint32_t
-#elif DATA_SIZE == 2
-#define SUFFIX w
-#define USUFFIX uw
-#define DATA_TYPE uint16_t
-#define DATA_STYPE int16_t
-#elif DATA_SIZE == 1
-#define SUFFIX b
-#define USUFFIX ub
-#define DATA_TYPE uint8_t
-#define DATA_STYPE int8_t
-#else
-#error unsupported data size
-#endif
-
-#if ACCESS_TYPE < (NB_MMU_MODES)
-
-#define CPU_MMU_INDEX ACCESS_TYPE
-#define MMUSUFFIX _mmu
-
-#elif ACCESS_TYPE == (NB_MMU_MODES)
-
-#define CPU_MMU_INDEX (cpu_mmu_index(env))
-#define MMUSUFFIX _mmu
-
-#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
-
-#define CPU_MMU_INDEX (cpu_mmu_index(env))
-#define MMUSUFFIX _cmmu
-
-#else
-#error invalid ACCESS_TYPE
-#endif
-
-#if DATA_SIZE == 8
-#define RES_TYPE uint64_t
-#else
-#define RES_TYPE uint32_t
-#endif
-
-#if ACCESS_TYPE == (NB_MMU_MODES + 1)
-#define ADDR_READ addr_code
-#else
-#define ADDR_READ addr_read
-#endif
-
-/* generic load/store macros */
-
-static inline RES_TYPE
-glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
-{
-    int page_index;
-    RES_TYPE res;
-    target_ulong addr;
-    int mmu_idx;
-
-    addr = ptr;
-    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    mmu_idx = CPU_MMU_INDEX;
-    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
-                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
-        res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx);
-    } else {
-        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
-    }
-    return res;
-}
-
-#if DATA_SIZE <= 2
-static inline int
-glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
-{
-    int res, page_index;
-    target_ulong addr;
-    int mmu_idx;
-
-    addr = ptr;
-    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    mmu_idx = CPU_MMU_INDEX;
-    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
-                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
-        res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX),
-                               MMUSUFFIX)(env, addr, mmu_idx);
-    } else {
-        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
-    }
-    return res;
-}
-#endif
-
-#if ACCESS_TYPE != (NB_MMU_MODES + 1)
-
-/* generic store macro */
-
-static inline void
-glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
-                                      RES_TYPE v)
-{
-    int page_index;
-    target_ulong addr;
-    int mmu_idx;
-
-    addr = ptr;
-    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    mmu_idx = CPU_MMU_INDEX;
-    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
-                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
-        glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx);
-    } else {
-        uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
-        glue(glue(st, SUFFIX), _raw)(hostaddr, v);
-    }
-}
-
-#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
-
-#if ACCESS_TYPE != (NB_MMU_MODES + 1)
-
-#if DATA_SIZE == 8
-static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env,
-                                                target_ulong ptr)
-{
-    union {
-        float64 d;
-        uint64_t i;
-    } u;
-    u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr);
-    return u.d;
-}
-
-static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env,
-                                             target_ulong ptr, float64 v)
-{
-    union {
-        float64 d;
-        uint64_t i;
-    } u;
-    u.d = v;
-    glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i);
-}
-#endif /* DATA_SIZE == 8 */
-
-#if DATA_SIZE == 4
-static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env,
-                                                target_ulong ptr)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr);
-    return u.f;
-}
-
-static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
-                                             target_ulong ptr, float32 v)
-{
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.f = v;
-    glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i);
-}
-#endif /* DATA_SIZE == 4 */
-
-#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
-
-#undef RES_TYPE
-#undef DATA_TYPE
-#undef DATA_STYPE
-#undef SUFFIX
-#undef USUFFIX
-#undef DATA_SIZE
-#undef CPU_MMU_INDEX
-#undef MMUSUFFIX
-#undef ADDR_READ
diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h
deleted file mode 100644 (file)
index 73ed7cf..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- *  Software MMU support
- *
- * Generate helpers used by TCG for qemu_ld/st ops and code load
- * functions.
- *
- * Included from target op helpers and exec.c.
- *
- *  Copyright (c) 2003 Fabrice Bellard
- *
- * 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/>.
- */
-#include "qemu/timer.h"
-#include "exec/address-spaces.h"
-#include "exec/memory.h"
-
-#define DATA_SIZE (1 << SHIFT)
-
-#if DATA_SIZE == 8
-#define SUFFIX q
-#define LSUFFIX q
-#define SDATA_TYPE  int64_t
-#define DATA_TYPE  uint64_t
-#elif DATA_SIZE == 4
-#define SUFFIX l
-#define LSUFFIX l
-#define SDATA_TYPE  int32_t
-#define DATA_TYPE  uint32_t
-#elif DATA_SIZE == 2
-#define SUFFIX w
-#define LSUFFIX uw
-#define SDATA_TYPE  int16_t
-#define DATA_TYPE  uint16_t
-#elif DATA_SIZE == 1
-#define SUFFIX b
-#define LSUFFIX ub
-#define SDATA_TYPE  int8_t
-#define DATA_TYPE  uint8_t
-#else
-#error unsupported data size
-#endif
-
-
-/* For the benefit of TCG generated code, we want to avoid the complication
-   of ABI-specific return type promotion and always return a value extended
-   to the register size of the host.  This is tcg_target_long, except in the
-   case of a 32-bit host and 64-bit data, and for that we always have
-   uint64_t.  Don't bother with this widened value for SOFTMMU_CODE_ACCESS.  */
-#if defined(SOFTMMU_CODE_ACCESS) || DATA_SIZE == 8
-# define WORD_TYPE  DATA_TYPE
-# define USUFFIX    SUFFIX
-#else
-# define WORD_TYPE  tcg_target_ulong
-# define USUFFIX    glue(u, SUFFIX)
-# define SSUFFIX    glue(s, SUFFIX)
-#endif
-
-#ifdef SOFTMMU_CODE_ACCESS
-#define READ_ACCESS_TYPE 2
-#define ADDR_READ addr_code
-#else
-#define READ_ACCESS_TYPE 0
-#define ADDR_READ addr_read
-#endif
-
-#if DATA_SIZE == 8
-# define BSWAP(X)  bswap64(X)
-#elif DATA_SIZE == 4
-# define BSWAP(X)  bswap32(X)
-#elif DATA_SIZE == 2
-# define BSWAP(X)  bswap16(X)
-#else
-# define BSWAP(X)  (X)
-#endif
-
-#ifdef TARGET_WORDS_BIGENDIAN
-# define TGT_BE(X)  (X)
-# define TGT_LE(X)  BSWAP(X)
-#else
-# define TGT_BE(X)  BSWAP(X)
-# define TGT_LE(X)  (X)
-#endif
-
-#if DATA_SIZE == 1
-# define helper_le_ld_name  glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
-# define helper_be_ld_name  helper_le_ld_name
-# define helper_le_lds_name glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)
-# define helper_be_lds_name helper_le_lds_name
-# define helper_le_st_name  glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)
-# define helper_be_st_name  helper_le_st_name
-#else
-# define helper_le_ld_name  glue(glue(helper_le_ld, USUFFIX), MMUSUFFIX)
-# define helper_be_ld_name  glue(glue(helper_be_ld, USUFFIX), MMUSUFFIX)
-# define helper_le_lds_name glue(glue(helper_le_ld, SSUFFIX), MMUSUFFIX)
-# define helper_be_lds_name glue(glue(helper_be_ld, SSUFFIX), MMUSUFFIX)
-# define helper_le_st_name  glue(glue(helper_le_st, SUFFIX), MMUSUFFIX)
-# define helper_be_st_name  glue(glue(helper_be_st, SUFFIX), MMUSUFFIX)
-#endif
-
-#ifdef TARGET_WORDS_BIGENDIAN
-# define helper_te_ld_name  helper_be_ld_name
-# define helper_te_st_name  helper_be_st_name
-#else
-# define helper_te_ld_name  helper_le_ld_name
-# define helper_te_st_name  helper_le_st_name
-#endif
-
-static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
-                                              hwaddr physaddr,
-                                              target_ulong addr,
-                                              uintptr_t retaddr)
-{
-    uint64_t val;
-    CPUState *cpu = ENV_GET_CPU(env);
-    MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr);
-
-    physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
-    cpu->mem_io_pc = retaddr;
-    if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) {
-        cpu_io_recompile(cpu, retaddr);
-    }
-
-    cpu->mem_io_vaddr = addr;
-    io_mem_read(mr, physaddr, &val, 1 << SHIFT);
-    return val;
-}
-
-#ifdef SOFTMMU_CODE_ACCESS
-static __attribute__((unused))
-#endif
-WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
-                            uintptr_t retaddr)
-{
-    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
-    uintptr_t haddr;
-    DATA_TYPE res;
-
-    /* Adjust the given return address.  */
-    retaddr -= GETPC_ADJ;
-
-    /* If the TLB entry is for a different page, reload and try again.  */
-    if ((addr & TARGET_PAGE_MASK)
-         != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-#ifdef ALIGNED_ONLY
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-        }
-#endif
-        tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-        tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
-    }
-
-    /* Handle an IO access.  */
-    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            goto do_unaligned_access;
-        }
-        ioaddr = env->iotlb[mmu_idx][index];
-
-        /* ??? Note that the io helpers always read data in the target
-           byte ordering.  We should push the LE/BE request down into io.  */
-        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
-        res = TGT_LE(res);
-        return res;
-    }
-
-    /* Handle slow unaligned access (it spans two pages or IO).  */
-    if (DATA_SIZE > 1
-        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
-                    >= TARGET_PAGE_SIZE)) {
-        target_ulong addr1, addr2;
-        DATA_TYPE res1, res2;
-        unsigned shift;
-    do_unaligned_access:
-#ifdef ALIGNED_ONLY
-        do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-#endif
-        addr1 = addr & ~(DATA_SIZE - 1);
-        addr2 = addr1 + DATA_SIZE;
-        /* Note the adjustment at the beginning of the function.
-           Undo that for the recursion.  */
-        res1 = helper_le_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
-        res2 = helper_le_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
-        shift = (addr & (DATA_SIZE - 1)) * 8;
-
-        /* Little-endian combine.  */
-        res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
-        return res;
-    }
-
-    /* Handle aligned access or unaligned access in the same page.  */
-#ifdef ALIGNED_ONLY
-    if ((addr & (DATA_SIZE - 1)) != 0) {
-        do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-    }
-#endif
-
-    haddr = addr + env->tlb_table[mmu_idx][index].addend;
-#if DATA_SIZE == 1
-    res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
-#else
-    res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr);
-#endif
-    return res;
-}
-
-#if DATA_SIZE > 1
-#ifdef SOFTMMU_CODE_ACCESS
-static __attribute__((unused))
-#endif
-WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
-                            uintptr_t retaddr)
-{
-    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
-    uintptr_t haddr;
-    DATA_TYPE res;
-
-    /* Adjust the given return address.  */
-    retaddr -= GETPC_ADJ;
-
-    /* If the TLB entry is for a different page, reload and try again.  */
-    if ((addr & TARGET_PAGE_MASK)
-         != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-#ifdef ALIGNED_ONLY
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-        }
-#endif
-        tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-        tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
-    }
-
-    /* Handle an IO access.  */
-    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            goto do_unaligned_access;
-        }
-        ioaddr = env->iotlb[mmu_idx][index];
-
-        /* ??? Note that the io helpers always read data in the target
-           byte ordering.  We should push the LE/BE request down into io.  */
-        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
-        res = TGT_BE(res);
-        return res;
-    }
-
-    /* Handle slow unaligned access (it spans two pages or IO).  */
-    if (DATA_SIZE > 1
-        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
-                    >= TARGET_PAGE_SIZE)) {
-        target_ulong addr1, addr2;
-        DATA_TYPE res1, res2;
-        unsigned shift;
-    do_unaligned_access:
-#ifdef ALIGNED_ONLY
-        do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-#endif
-        addr1 = addr & ~(DATA_SIZE - 1);
-        addr2 = addr1 + DATA_SIZE;
-        /* Note the adjustment at the beginning of the function.
-           Undo that for the recursion.  */
-        res1 = helper_be_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
-        res2 = helper_be_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
-        shift = (addr & (DATA_SIZE - 1)) * 8;
-
-        /* Big-endian combine.  */
-        res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
-        return res;
-    }
-
-    /* Handle aligned access or unaligned access in the same page.  */
-#ifdef ALIGNED_ONLY
-    if ((addr & (DATA_SIZE - 1)) != 0) {
-        do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-    }
-#endif
-
-    haddr = addr + env->tlb_table[mmu_idx][index].addend;
-    res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
-    return res;
-}
-#endif /* DATA_SIZE > 1 */
-
-DATA_TYPE
-glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
-                                         int mmu_idx)
-{
-    return helper_te_ld_name (env, addr, mmu_idx, GETRA());
-}
-
-#ifndef SOFTMMU_CODE_ACCESS
-
-/* Provide signed versions of the load routines as well.  We can of course
-   avoid this for 64-bit data, or for 32-bit data on 32-bit host.  */
-#if DATA_SIZE * 8 < TCG_TARGET_REG_BITS
-WORD_TYPE helper_le_lds_name(CPUArchState *env, target_ulong addr,
-                             int mmu_idx, uintptr_t retaddr)
-{
-    return (SDATA_TYPE)helper_le_ld_name(env, addr, mmu_idx, retaddr);
-}
-
-# if DATA_SIZE > 1
-WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
-                             int mmu_idx, uintptr_t retaddr)
-{
-    return (SDATA_TYPE)helper_be_ld_name(env, addr, mmu_idx, retaddr);
-}
-# endif
-#endif
-
-static inline void glue(io_write, SUFFIX)(CPUArchState *env,
-                                          hwaddr physaddr,
-                                          DATA_TYPE val,
-                                          target_ulong addr,
-                                          uintptr_t retaddr)
-{
-    CPUState *cpu = ENV_GET_CPU(env);
-    MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr);
-
-    physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
-    if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) {
-        cpu_io_recompile(cpu, retaddr);
-    }
-
-    cpu->mem_io_vaddr = addr;
-    cpu->mem_io_pc = retaddr;
-    io_mem_write(mr, physaddr, val, 1 << SHIFT);
-}
-
-void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
-                       int mmu_idx, uintptr_t retaddr)
-{
-    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
-    uintptr_t haddr;
-
-    /* Adjust the given return address.  */
-    retaddr -= GETPC_ADJ;
-
-    /* If the TLB entry is for a different page, reload and try again.  */
-    if ((addr & TARGET_PAGE_MASK)
-        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-#ifdef ALIGNED_ONLY
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
-        }
-#endif
-        tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
-        tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
-    }
-
-    /* Handle an IO access.  */
-    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            goto do_unaligned_access;
-        }
-        ioaddr = env->iotlb[mmu_idx][index];
-
-        /* ??? Note that the io helpers always read data in the target
-           byte ordering.  We should push the LE/BE request down into io.  */
-        val = TGT_LE(val);
-        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
-        return;
-    }
-
-    /* Handle slow unaligned access (it spans two pages or IO).  */
-    if (DATA_SIZE > 1
-        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
-                     >= TARGET_PAGE_SIZE)) {
-        int i;
-    do_unaligned_access:
-#ifdef ALIGNED_ONLY
-        do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
-#endif
-        /* XXX: not efficient, but simple */
-        /* Note: relies on the fact that tlb_fill() does not remove the
-         * previous page from the TLB cache.  */
-        for (i = DATA_SIZE - 1; i >= 0; i--) {
-            /* Little-endian extract.  */
-            uint8_t val8 = val >> (i * 8);
-            /* Note the adjustment at the beginning of the function.
-               Undo that for the recursion.  */
-            glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
-                                            mmu_idx, retaddr + GETPC_ADJ);
-        }
-        return;
-    }
-
-    /* Handle aligned access or unaligned access in the same page.  */
-#ifdef ALIGNED_ONLY
-    if ((addr & (DATA_SIZE - 1)) != 0) {
-        do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
-    }
-#endif
-
-    haddr = addr + env->tlb_table[mmu_idx][index].addend;
-#if DATA_SIZE == 1
-    glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
-#else
-    glue(glue(st, SUFFIX), _le_p)((uint8_t *)haddr, val);
-#endif
-}
-
-#if DATA_SIZE > 1
-void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
-                       int mmu_idx, uintptr_t retaddr)
-{
-    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
-    uintptr_t haddr;
-
-    /* Adjust the given return address.  */
-    retaddr -= GETPC_ADJ;
-
-    /* If the TLB entry is for a different page, reload and try again.  */
-    if ((addr & TARGET_PAGE_MASK)
-        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-#ifdef ALIGNED_ONLY
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
-        }
-#endif
-        tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
-        tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
-    }
-
-    /* Handle an IO access.  */
-    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
-        if ((addr & (DATA_SIZE - 1)) != 0) {
-            goto do_unaligned_access;
-        }
-        ioaddr = env->iotlb[mmu_idx][index];
-
-        /* ??? Note that the io helpers always read data in the target
-           byte ordering.  We should push the LE/BE request down into io.  */
-        val = TGT_BE(val);
-        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
-        return;
-    }
-
-    /* Handle slow unaligned access (it spans two pages or IO).  */
-    if (DATA_SIZE > 1
-        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
-                     >= TARGET_PAGE_SIZE)) {
-        int i;
-    do_unaligned_access:
-#ifdef ALIGNED_ONLY
-        do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
-#endif
-        /* XXX: not efficient, but simple */
-        /* Note: relies on the fact that tlb_fill() does not remove the
-         * previous page from the TLB cache.  */
-        for (i = DATA_SIZE - 1; i >= 0; i--) {
-            /* Big-endian extract.  */
-            uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
-            /* Note the adjustment at the beginning of the function.
-               Undo that for the recursion.  */
-            glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
-                                            mmu_idx, retaddr + GETPC_ADJ);
-        }
-        return;
-    }
-
-    /* Handle aligned access or unaligned access in the same page.  */
-#ifdef ALIGNED_ONLY
-    if ((addr & (DATA_SIZE - 1)) != 0) {
-        do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
-    }
-#endif
-
-    haddr = addr + env->tlb_table[mmu_idx][index].addend;
-    glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
-}
-#endif /* DATA_SIZE > 1 */
-
-void
-glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
-                                         DATA_TYPE val, int mmu_idx)
-{
-    helper_te_st_name(env, addr, val, mmu_idx, GETRA());
-}
-
-#endif /* !defined(SOFTMMU_CODE_ACCESS) */
-
-#undef READ_ACCESS_TYPE
-#undef SHIFT
-#undef DATA_TYPE
-#undef SUFFIX
-#undef LSUFFIX
-#undef DATA_SIZE
-#undef ADDR_READ
-#undef WORD_TYPE
-#undef SDATA_TYPE
-#undef USUFFIX
-#undef SSUFFIX
-#undef BSWAP
-#undef TGT_BE
-#undef TGT_LE
-#undef CPU_BE
-#undef CPU_LE
-#undef helper_le_ld_name
-#undef helper_be_ld_name
-#undef helper_le_lds_name
-#undef helper_be_lds_name
-#undef helper_le_st_name
-#undef helper_be_st_name
-#undef helper_te_ld_name
-#undef helper_te_st_name
index 31328a81572de69cfc53c5a66c87953d3b866da3..fa9d99792a5e1d4eaa753fb4949f9f4285790cf2 100644 (file)
@@ -275,6 +275,21 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
             .driver   = "nec-usb-xhci",\
             .property = "superspeed-ports-first",\
             .value    = "off",\
+        },\
+        {\
+            .driver   = "pci-serial",\
+            .property = "prog_if",\
+            .value    = stringify(0),\
+        },\
+        {\
+            .driver   = "pci-serial-2x",\
+            .property = "prof_if",\
+            .value    = stringify(0),\
+        },\
+        {\
+            .driver   = "pci-serial-4x",\
+            .property = "prog_if",\
+            .value    = stringify(0),\
         }
 
 #define PC_COMPAT_1_7 \
index 6d854b7f1e20930a41a9b06f93b4fe250668be1a..a3f4d88bf011a6808c364b0307ee0d81705a22e9 100644 (file)
@@ -64,7 +64,7 @@ struct smbios_type_0 {
     uint16_t bios_starting_address_segment;
     uint8_t bios_release_date_str;
     uint8_t bios_rom_size;
-    uint8_t bios_characteristics[8];
+    uint64_t bios_characteristics;
     uint8_t bios_characteristics_extension_bytes[2];
     uint8_t system_bios_major_release;
     uint8_t system_bios_minor_release;
@@ -182,10 +182,10 @@ struct smbios_type_17 {
     uint8_t part_number_str;
     uint8_t attributes;
     uint32_t extended_size;
-    uint32_t configured_clock_speed;
-    uint32_t minimum_voltage;
-    uint32_t maximum_voltage;
-    uint32_t configured_voltage;
+    uint16_t configured_clock_speed;
+    uint16_t minimum_voltage;
+    uint16_t maximum_voltage;
+    uint16_t configured_voltage;
 } QEMU_PACKED;
 
 /* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */
index acca45ed586b2d42955caf2d0f642071cb565fed..ff44ef6fcabe84be0ffcfe5894517c022f2f1968 100644 (file)
@@ -49,7 +49,6 @@ struct PCIExpressHost {
     MemoryRegion mmio;
 };
 
-int pcie_host_init(PCIExpressHost *e);
 void pcie_host_mmcfg_unmap(PCIExpressHost *e);
 void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size);
 void pcie_host_mmcfg_update(PCIExpressHost *e,
index ae31575577d8fef33eeb07e3f3383aef2dc02819..9221cfc8794ddd78ca8d0902fa934b50e02fab5d 100644 (file)
@@ -239,10 +239,18 @@ struct PropertyInfo {
     ObjectPropertyRelease *release;
 };
 
+/**
+ * GlobalProperty:
+ * @not_used: Track use of a global property.  Defaults to false in all C99
+ * struct initializations.
+ *
+ * This prevents reports of .compat_props when they are not used.
+ */
 typedef struct GlobalProperty {
     const char *driver;
     const char *property;
     const char *value;
+    bool not_used;
     QTAILQ_ENTRY(GlobalProperty) next;
 } GlobalProperty;
 
index c46e908d71a58b04a89a6c719d441b502f039ca4..c962b6bbaad6b2d401daab12c6c02765a8942133 100644 (file)
@@ -180,6 +180,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
 
 void qdev_prop_register_global(GlobalProperty *prop);
 void qdev_prop_register_global_list(GlobalProperty *props);
+int qdev_prop_check_global(void);
 void qdev_prop_set_globals(DeviceState *dev, Error **errp);
 void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
                                     Error **errp);
index df977c88f0b80f418624a966269156ecd74590d7..4b352a28fac55bc49e65b856dc5ba85cbbdb5bc8 100644 (file)
@@ -80,6 +80,8 @@ struct TranslationBlock;
  * @has_work: Callback for checking if there is work to do.
  * @do_interrupt: Callback for interrupt handling.
  * @do_unassigned_access: Callback for unassigned access handling.
+ * @do_unaligned_access: Callback for unaligned access handling, if
+ * the target defines #ALIGNED_ONLY.
  * @memory_rw_debug: Callback for GDB memory access.
  * @dump_state: Callback for dumping state.
  * @dump_statistics: Callback for dumping statistics.
@@ -112,6 +114,8 @@ typedef struct CPUClass {
     bool (*has_work)(CPUState *cpu);
     void (*do_interrupt)(CPUState *cpu);
     CPUUnassignedAccess do_unassigned_access;
+    void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
+                                int is_write, int is_user, uintptr_t retaddr);
     int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
                            uint8_t *buf, int len, bool is_write);
     void (*dump_state)(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
@@ -544,8 +548,7 @@ void cpu_interrupt(CPUState *cpu, int mask);
 
 #endif /* USER_ONLY */
 
-#ifndef CONFIG_USER_ONLY
-
+#ifdef CONFIG_SOFTMMU
 static inline void cpu_unassigned_access(CPUState *cpu, hwaddr addr,
                                          bool is_write, bool is_exec,
                                          int opaque, unsigned size)
@@ -557,6 +560,14 @@ static inline void cpu_unassigned_access(CPUState *cpu, hwaddr addr,
     }
 }
 
+static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
+                                        int is_write, int is_user,
+                                        uintptr_t retaddr)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+
+    return cc->do_unaligned_access(cpu, addr, is_write, is_user, retaddr);
+}
 #endif
 
 /**
index aa99b0cac70c1af167b539c01ccfc25dd1bdaa2b..5d5ac00663a7d574dbbb576ce6968dee8c755d4a 100644 (file)
@@ -39,6 +39,7 @@ InputEvent *qemu_input_event_new_key(KeyValue *key, bool down);
 void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down);
 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down);
 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down);
+void qemu_input_event_send_key_delay(uint32_t delay_ms);
 int qemu_input_key_number_to_qcode(uint8_t nr);
 int qemu_input_key_value_to_number(const KeyValue *value);
 int qemu_input_key_value_to_qcode(const KeyValue *value);
index 721a3904a9bd278b6bc52d23c8c2e6b82615d291..4e19eff0efeea85a47ab8b76b64601a2b6c73bf7 100644 (file)
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1410,7 +1410,7 @@ int kvm_init(MachineClass *mc)
 
     ret = kvm_ioctl(s, KVM_GET_API_VERSION, 0);
     if (ret < KVM_API_VERSION) {
-        if (ret > 0) {
+        if (ret >= 0) {
             ret = -EINVAL;
         }
         fprintf(stderr, "kvm version too old\n");
@@ -1461,6 +1461,7 @@ int kvm_init(MachineClass *mc)
     if (mc->kvm_type) {
         type = mc->kvm_type(kvm_type);
     } else if (kvm_type) {
+        ret = -EINVAL;
         fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type);
         goto err;
     }
@@ -1561,6 +1562,7 @@ int kvm_init(MachineClass *mc)
     return 0;
 
 err:
+    assert(ret < 0);
     if (s->vmfd >= 0) {
         close(s->vmfd);
     }
index 882186e1a0340ab73b7159688e33b43c03637e35..3e210240566ed0d275b562405c581b5a9ac81067 100644 (file)
@@ -4052,7 +4052,7 @@ int main(int argc, char **argv, char **envp)
 
 #if defined(TARGET_I386)
     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
-    env->hflags |= HF_PE_MASK;
+    env->hflags |= HF_PE_MASK | HF_CPL_MASK;
     if (env->features[FEAT_1_EDX] & CPUID_SSE) {
         env->cr[4] |= CR4_OSFXSR_MASK;
         env->hflags |= HF_OSFXSR_MASK;
index 36d4a738ea2cd16264223e648f9d16ccc9f7401c..ba3d8ab378f4300a92d01aa0a482181b6638b74a 100644 (file)
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #include "cpu.h"
+#include "exec/cpu_ldst.h"
 
 #undef DEBUG_REMAP
 #ifdef DEBUG_REMAP
index 593679a17a2fc62cddf33922c30062ac797ca17b..0565816910481ac4877e7175ea09f51de33a0d29 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -66,6 +66,7 @@
 #include "trace/simple.h"
 #endif
 #include "exec/memory.h"
+#include "exec/cpu_ldst.h"
 #include "qmp-commands.h"
 #include "hmp.h"
 #include "qemu/thread.h"
index 4011d46d625e1a95b2709277cf693608c5de239c..d0714c43a669cb20e68ae22b948b54bd498bd092 100644 (file)
@@ -1341,7 +1341,7 @@ ETEXI
 DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
     "-smbios file=binary\n"
     "                load SMBIOS entry from binary file\n"
-    "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n"
+    "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d][,uefi=on|off]\n"
     "                specify SMBIOS type 0 fields\n"
     "-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n"
     "              [,uuid=uuid][,sku=str][,family=str]\n"
@@ -1351,7 +1351,7 @@ STEXI
 @findex -smbios
 Load SMBIOS entry from binary file.
 
-@item -smbios type=0[,vendor=@var{str}][,version=@var{str}][,date=@var{str}][,release=@var{%d.%d}]
+@item -smbios type=0[,vendor=@var{str}][,version=@var{str}][,date=@var{str}][,release=@var{%d.%d}][,uefi=on|off]
 Specify SMBIOS type 0 fields
 
 @item -smbios type=1[,manufacturer=@var{str}][,product=@var{str}] [,version=@var{str}][,serial=@var{str}][,uuid=@var{uuid}][,sku=@var{str}] [,family=@var{str}]
index d793dd0c8565f2d906fa420dd869584d6269e2a3..e76939651a08ddef92f5124b9423758fc3cafea7 100644 (file)
@@ -31,7 +31,7 @@
 
 static void acquire_privilege(const char *name, Error **errp)
 {
-    HANDLE token;
+    HANDLE token = NULL;
     TOKEN_PRIVILEGES priv;
     Error *local_err = NULL;
 
@@ -53,13 +53,15 @@ static void acquire_privilege(const char *name, Error **errp)
             goto out;
         }
 
-        CloseHandle(token);
     } else {
         error_set(&local_err, QERR_QGA_COMMAND_FAILED,
                   "failed to open privilege token");
     }
 
 out:
+    if (token) {
+        CloseHandle(token);
+    }
     if (local_err) {
         error_propagate(errp, local_err);
     }
index 762544b197bff0c0565e852a6363c951fbe44877..d7e97e7488cdbe346a24087ad0e5c9df611d9e5f 100755 (executable)
@@ -352,8 +352,8 @@ class TracepointProvider(object):
         return ret
 
 class Stats:
-    def __init__(self, provider, fields = None):
-        self.provider = provider
+    def __init__(self, providers, fields = None):
+        self.providers = providers
         self.fields_filter = fields
         self._update()
     def _update(self):
@@ -362,22 +362,25 @@ class Stats:
             if not self.fields_filter:
                 return True
             return re.match(self.fields_filter, key) is not None
-        self.values = dict([(key, None)
-                            for key in provider.fields()
-                            if wanted(key)])
-        self.provider.select(self.values.keys())
+        self.values = dict()
+        for d in providers:
+            provider_fields = [key for key in d.fields() if wanted(key)]
+            for key in provider_fields:
+                self.values[key] = None
+            d.select(provider_fields)
     def set_fields_filter(self, fields_filter):
         self.fields_filter = fields_filter
         self._update()
     def get(self):
-        new = self.provider.read()
-        for key in self.provider.fields():
-            oldval = self.values.get(key, (0, 0))
-            newval = new[key]
-            newdelta = None
-            if oldval is not None:
-                newdelta = newval - oldval[0]
-            self.values[key] = (newval, newdelta)
+        for d in providers:
+            new = d.read()
+            for key in d.fields():
+                oldval = self.values.get(key, (0, 0))
+                newval = new[key]
+                newdelta = None
+                if oldval is not None:
+                    newdelta = newval - oldval[0]
+                self.values[key] = (newval, newdelta)
         return self.values
 
 if not os.access('/sys/kernel/debug', os.F_OK):
@@ -487,6 +490,18 @@ options.add_option('-l', '--log',
                    dest = 'log',
                    help = 'run in logging mode (like vmstat)',
                    )
+options.add_option('-t', '--tracepoints',
+                   action = 'store_true',
+                   default = False,
+                   dest = 'tracepoints',
+                   help = 'retrieve statistics from tracepoints',
+                   )
+options.add_option('-d', '--debugfs',
+                   action = 'store_true',
+                   default = False,
+                   dest = 'debugfs',
+                   help = 'retrieve statistics from debugfs',
+                   )
 options.add_option('-f', '--fields',
                    action = 'store',
                    default = None,
@@ -495,12 +510,19 @@ options.add_option('-f', '--fields',
                    )
 (options, args) = options.parse_args(sys.argv)
 
-try:
-    provider = TracepointProvider()
-except:
-    provider = DebugfsProvider()
+providers = []
+if options.tracepoints:
+    providers.append(TracepointProvider())
+if options.debugfs:
+    providers.append(DebugfsProvider())
+
+if len(providers) == 0:
+    try:
+        providers = [TracepointProvider()]
+    except:
+        providers = [DebugfsProvider()]
 
-stats = Stats(provider, fields = options.fields)
+stats = Stats(providers, fields = options.fields)
 
 if options.log:
     log(stats)
index ecdb0baee4fc54a71958e04d89f85c2379b0760a..bcaeb4486056ef34e55e971f1e026b6ed106c001 100644 (file)
@@ -37,12 +37,7 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
                 ethaddr[0], ethaddr[1], ethaddr[2],
                 ethaddr[3], ethaddr[4], ethaddr[5]));
 
-    /* Check 0.0.0.0/8 invalid source-only addresses */
-    if ((ip_addr & htonl(~(0xfU << 28))) == 0) {
-        return;
-    }
-
-    if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
+    if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
         /* Do not register broadcast addresses */
         return;
     }
@@ -73,9 +68,6 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
     DEBUG_CALL("arp_table_search");
     DEBUG_ARG("ip = 0x%x", ip_addr);
 
-    /* Check 0.0.0.0/8 invalid source-only addresses */
-    assert((ip_addr & htonl(~(0xfU << 28))) != 0);
-
     /* If broadcast address */
     if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
         /* return Ethernet broadcast address */
index 3fb48a49212f69ff5385d354164eaf5162ac4c96..60280361e6e79e31a36720df8b6f91de9691eab8 100644 (file)
@@ -778,6 +778,11 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
         return 1;
     }
 
+    if (iph->ip_dst.s_addr == 0) {
+        /* 0.0.0.0 can not be a destination address, something went wrong,
+         * avoid making it worse */
+        return 1;
+    }
     if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
         uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
         struct ethhdr *reh = (struct ethhdr *)arp_req;
diff --git a/softmmu_template.h b/softmmu_template.h
new file mode 100644 (file)
index 0000000..5a07f99
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ *  Software MMU support
+ *
+ * Generate helpers used by TCG for qemu_ld/st ops and code load
+ * functions.
+ *
+ * Included from target op helpers and exec.c.
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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/>.
+ */
+#include "qemu/timer.h"
+#include "exec/address-spaces.h"
+#include "exec/memory.h"
+
+#define DATA_SIZE (1 << SHIFT)
+
+#if DATA_SIZE == 8
+#define SUFFIX q
+#define LSUFFIX q
+#define SDATA_TYPE  int64_t
+#define DATA_TYPE  uint64_t
+#elif DATA_SIZE == 4
+#define SUFFIX l
+#define LSUFFIX l
+#define SDATA_TYPE  int32_t
+#define DATA_TYPE  uint32_t
+#elif DATA_SIZE == 2
+#define SUFFIX w
+#define LSUFFIX uw
+#define SDATA_TYPE  int16_t
+#define DATA_TYPE  uint16_t
+#elif DATA_SIZE == 1
+#define SUFFIX b
+#define LSUFFIX ub
+#define SDATA_TYPE  int8_t
+#define DATA_TYPE  uint8_t
+#else
+#error unsupported data size
+#endif
+
+
+/* For the benefit of TCG generated code, we want to avoid the complication
+   of ABI-specific return type promotion and always return a value extended
+   to the register size of the host.  This is tcg_target_long, except in the
+   case of a 32-bit host and 64-bit data, and for that we always have
+   uint64_t.  Don't bother with this widened value for SOFTMMU_CODE_ACCESS.  */
+#if defined(SOFTMMU_CODE_ACCESS) || DATA_SIZE == 8
+# define WORD_TYPE  DATA_TYPE
+# define USUFFIX    SUFFIX
+#else
+# define WORD_TYPE  tcg_target_ulong
+# define USUFFIX    glue(u, SUFFIX)
+# define SSUFFIX    glue(s, SUFFIX)
+#endif
+
+#ifdef SOFTMMU_CODE_ACCESS
+#define READ_ACCESS_TYPE 2
+#define ADDR_READ addr_code
+#else
+#define READ_ACCESS_TYPE 0
+#define ADDR_READ addr_read
+#endif
+
+#if DATA_SIZE == 8
+# define BSWAP(X)  bswap64(X)
+#elif DATA_SIZE == 4
+# define BSWAP(X)  bswap32(X)
+#elif DATA_SIZE == 2
+# define BSWAP(X)  bswap16(X)
+#else
+# define BSWAP(X)  (X)
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+# define TGT_BE(X)  (X)
+# define TGT_LE(X)  BSWAP(X)
+#else
+# define TGT_BE(X)  BSWAP(X)
+# define TGT_LE(X)  (X)
+#endif
+
+#if DATA_SIZE == 1
+# define helper_le_ld_name  glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
+# define helper_be_ld_name  helper_le_ld_name
+# define helper_le_lds_name glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)
+# define helper_be_lds_name helper_le_lds_name
+# define helper_le_st_name  glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)
+# define helper_be_st_name  helper_le_st_name
+#else
+# define helper_le_ld_name  glue(glue(helper_le_ld, USUFFIX), MMUSUFFIX)
+# define helper_be_ld_name  glue(glue(helper_be_ld, USUFFIX), MMUSUFFIX)
+# define helper_le_lds_name glue(glue(helper_le_ld, SSUFFIX), MMUSUFFIX)
+# define helper_be_lds_name glue(glue(helper_be_ld, SSUFFIX), MMUSUFFIX)
+# define helper_le_st_name  glue(glue(helper_le_st, SUFFIX), MMUSUFFIX)
+# define helper_be_st_name  glue(glue(helper_be_st, SUFFIX), MMUSUFFIX)
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+# define helper_te_ld_name  helper_be_ld_name
+# define helper_te_st_name  helper_be_st_name
+#else
+# define helper_te_ld_name  helper_le_ld_name
+# define helper_te_st_name  helper_le_st_name
+#endif
+
+#ifndef SOFTMMU_CODE_ACCESS
+static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
+                                              hwaddr physaddr,
+                                              target_ulong addr,
+                                              uintptr_t retaddr)
+{
+    uint64_t val;
+    CPUState *cpu = ENV_GET_CPU(env);
+    MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr);
+
+    physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
+    cpu->mem_io_pc = retaddr;
+    if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) {
+        cpu_io_recompile(cpu, retaddr);
+    }
+
+    cpu->mem_io_vaddr = addr;
+    io_mem_read(mr, physaddr, &val, 1 << SHIFT);
+    return val;
+}
+#endif
+
+#ifdef SOFTMMU_CODE_ACCESS
+static __attribute__((unused))
+#endif
+WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
+                            uintptr_t retaddr)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+    uintptr_t haddr;
+    DATA_TYPE res;
+
+    /* Adjust the given return address.  */
+    retaddr -= GETPC_ADJ;
+
+    /* If the TLB entry is for a different page, reload and try again.  */
+    if ((addr & TARGET_PAGE_MASK)
+         != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
+                                 mmu_idx, retaddr);
+        }
+#endif
+        tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+        tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+    }
+
+    /* Handle an IO access.  */
+    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+        hwaddr ioaddr;
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            goto do_unaligned_access;
+        }
+        ioaddr = env->iotlb[mmu_idx][index];
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+        res = TGT_LE(res);
+        return res;
+    }
+
+    /* Handle slow unaligned access (it spans two pages or IO).  */
+    if (DATA_SIZE > 1
+        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+                    >= TARGET_PAGE_SIZE)) {
+        target_ulong addr1, addr2;
+        DATA_TYPE res1, res2;
+        unsigned shift;
+    do_unaligned_access:
+#ifdef ALIGNED_ONLY
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
+                             mmu_idx, retaddr);
+#endif
+        addr1 = addr & ~(DATA_SIZE - 1);
+        addr2 = addr1 + DATA_SIZE;
+        /* Note the adjustment at the beginning of the function.
+           Undo that for the recursion.  */
+        res1 = helper_le_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
+        res2 = helper_le_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
+        shift = (addr & (DATA_SIZE - 1)) * 8;
+
+        /* Little-endian combine.  */
+        res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
+        return res;
+    }
+
+    /* Handle aligned access or unaligned access in the same page.  */
+#ifdef ALIGNED_ONLY
+    if ((addr & (DATA_SIZE - 1)) != 0) {
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
+                             mmu_idx, retaddr);
+    }
+#endif
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+#if DATA_SIZE == 1
+    res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
+#else
+    res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr);
+#endif
+    return res;
+}
+
+#if DATA_SIZE > 1
+#ifdef SOFTMMU_CODE_ACCESS
+static __attribute__((unused))
+#endif
+WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
+                            uintptr_t retaddr)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+    uintptr_t haddr;
+    DATA_TYPE res;
+
+    /* Adjust the given return address.  */
+    retaddr -= GETPC_ADJ;
+
+    /* If the TLB entry is for a different page, reload and try again.  */
+    if ((addr & TARGET_PAGE_MASK)
+         != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
+                                 mmu_idx, retaddr);
+        }
+#endif
+        tlb_fill(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+        tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+    }
+
+    /* Handle an IO access.  */
+    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+        hwaddr ioaddr;
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            goto do_unaligned_access;
+        }
+        ioaddr = env->iotlb[mmu_idx][index];
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+        res = TGT_BE(res);
+        return res;
+    }
+
+    /* Handle slow unaligned access (it spans two pages or IO).  */
+    if (DATA_SIZE > 1
+        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+                    >= TARGET_PAGE_SIZE)) {
+        target_ulong addr1, addr2;
+        DATA_TYPE res1, res2;
+        unsigned shift;
+    do_unaligned_access:
+#ifdef ALIGNED_ONLY
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
+                             mmu_idx, retaddr);
+#endif
+        addr1 = addr & ~(DATA_SIZE - 1);
+        addr2 = addr1 + DATA_SIZE;
+        /* Note the adjustment at the beginning of the function.
+           Undo that for the recursion.  */
+        res1 = helper_be_ld_name(env, addr1, mmu_idx, retaddr + GETPC_ADJ);
+        res2 = helper_be_ld_name(env, addr2, mmu_idx, retaddr + GETPC_ADJ);
+        shift = (addr & (DATA_SIZE - 1)) * 8;
+
+        /* Big-endian combine.  */
+        res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
+        return res;
+    }
+
+    /* Handle aligned access or unaligned access in the same page.  */
+#ifdef ALIGNED_ONLY
+    if ((addr & (DATA_SIZE - 1)) != 0) {
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
+                             mmu_idx, retaddr);
+    }
+#endif
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+    res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
+    return res;
+}
+#endif /* DATA_SIZE > 1 */
+
+DATA_TYPE
+glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
+                                         int mmu_idx)
+{
+    return helper_te_ld_name (env, addr, mmu_idx, GETRA());
+}
+
+#ifndef SOFTMMU_CODE_ACCESS
+
+/* Provide signed versions of the load routines as well.  We can of course
+   avoid this for 64-bit data, or for 32-bit data on 32-bit host.  */
+#if DATA_SIZE * 8 < TCG_TARGET_REG_BITS
+WORD_TYPE helper_le_lds_name(CPUArchState *env, target_ulong addr,
+                             int mmu_idx, uintptr_t retaddr)
+{
+    return (SDATA_TYPE)helper_le_ld_name(env, addr, mmu_idx, retaddr);
+}
+
+# if DATA_SIZE > 1
+WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
+                             int mmu_idx, uintptr_t retaddr)
+{
+    return (SDATA_TYPE)helper_be_ld_name(env, addr, mmu_idx, retaddr);
+}
+# endif
+#endif
+
+static inline void glue(io_write, SUFFIX)(CPUArchState *env,
+                                          hwaddr physaddr,
+                                          DATA_TYPE val,
+                                          target_ulong addr,
+                                          uintptr_t retaddr)
+{
+    CPUState *cpu = ENV_GET_CPU(env);
+    MemoryRegion *mr = iotlb_to_region(cpu->as, physaddr);
+
+    physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
+    if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu_can_do_io(cpu)) {
+        cpu_io_recompile(cpu, retaddr);
+    }
+
+    cpu->mem_io_vaddr = addr;
+    cpu->mem_io_pc = retaddr;
+    io_mem_write(mr, physaddr, val, 1 << SHIFT);
+}
+
+void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
+                       int mmu_idx, uintptr_t retaddr)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+    uintptr_t haddr;
+
+    /* Adjust the given return address.  */
+    retaddr -= GETPC_ADJ;
+
+    /* If the TLB entry is for a different page, reload and try again.  */
+    if ((addr & TARGET_PAGE_MASK)
+        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        }
+#endif
+        tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+    }
+
+    /* Handle an IO access.  */
+    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+        hwaddr ioaddr;
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            goto do_unaligned_access;
+        }
+        ioaddr = env->iotlb[mmu_idx][index];
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        val = TGT_LE(val);
+        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
+        return;
+    }
+
+    /* Handle slow unaligned access (it spans two pages or IO).  */
+    if (DATA_SIZE > 1
+        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+                     >= TARGET_PAGE_SIZE)) {
+        int i;
+    do_unaligned_access:
+#ifdef ALIGNED_ONLY
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+#endif
+        /* XXX: not efficient, but simple */
+        /* Note: relies on the fact that tlb_fill() does not remove the
+         * previous page from the TLB cache.  */
+        for (i = DATA_SIZE - 1; i >= 0; i--) {
+            /* Little-endian extract.  */
+            uint8_t val8 = val >> (i * 8);
+            /* Note the adjustment at the beginning of the function.
+               Undo that for the recursion.  */
+            glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
+                                            mmu_idx, retaddr + GETPC_ADJ);
+        }
+        return;
+    }
+
+    /* Handle aligned access or unaligned access in the same page.  */
+#ifdef ALIGNED_ONLY
+    if ((addr & (DATA_SIZE - 1)) != 0) {
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+    }
+#endif
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+#if DATA_SIZE == 1
+    glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
+#else
+    glue(glue(st, SUFFIX), _le_p)((uint8_t *)haddr, val);
+#endif
+}
+
+#if DATA_SIZE > 1
+void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
+                       int mmu_idx, uintptr_t retaddr)
+{
+    int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+    uintptr_t haddr;
+
+    /* Adjust the given return address.  */
+    retaddr -= GETPC_ADJ;
+
+    /* If the TLB entry is for a different page, reload and try again.  */
+    if ((addr & TARGET_PAGE_MASK)
+        != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+#ifdef ALIGNED_ONLY
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        }
+#endif
+        tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+        tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+    }
+
+    /* Handle an IO access.  */
+    if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+        hwaddr ioaddr;
+        if ((addr & (DATA_SIZE - 1)) != 0) {
+            goto do_unaligned_access;
+        }
+        ioaddr = env->iotlb[mmu_idx][index];
+
+        /* ??? Note that the io helpers always read data in the target
+           byte ordering.  We should push the LE/BE request down into io.  */
+        val = TGT_BE(val);
+        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
+        return;
+    }
+
+    /* Handle slow unaligned access (it spans two pages or IO).  */
+    if (DATA_SIZE > 1
+        && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+                     >= TARGET_PAGE_SIZE)) {
+        int i;
+    do_unaligned_access:
+#ifdef ALIGNED_ONLY
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+#endif
+        /* XXX: not efficient, but simple */
+        /* Note: relies on the fact that tlb_fill() does not remove the
+         * previous page from the TLB cache.  */
+        for (i = DATA_SIZE - 1; i >= 0; i--) {
+            /* Big-endian extract.  */
+            uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
+            /* Note the adjustment at the beginning of the function.
+               Undo that for the recursion.  */
+            glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
+                                            mmu_idx, retaddr + GETPC_ADJ);
+        }
+        return;
+    }
+
+    /* Handle aligned access or unaligned access in the same page.  */
+#ifdef ALIGNED_ONLY
+    if ((addr & (DATA_SIZE - 1)) != 0) {
+        cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
+    }
+#endif
+
+    haddr = addr + env->tlb_table[mmu_idx][index].addend;
+    glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
+}
+#endif /* DATA_SIZE > 1 */
+
+void
+glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
+                                         DATA_TYPE val, int mmu_idx)
+{
+    helper_te_st_name(env, addr, val, mmu_idx, GETRA());
+}
+
+#endif /* !defined(SOFTMMU_CODE_ACCESS) */
+
+#undef READ_ACCESS_TYPE
+#undef SHIFT
+#undef DATA_TYPE
+#undef SUFFIX
+#undef LSUFFIX
+#undef DATA_SIZE
+#undef ADDR_READ
+#undef WORD_TYPE
+#undef SDATA_TYPE
+#undef USUFFIX
+#undef SSUFFIX
+#undef BSWAP
+#undef TGT_BE
+#undef TGT_LE
+#undef CPU_BE
+#undef CPU_LE
+#undef helper_le_ld_name
+#undef helper_be_ld_name
+#undef helper_le_lds_name
+#undef helper_be_lds_name
+#undef helper_le_st_name
+#undef helper_be_st_name
+#undef helper_te_ld_name
+#undef helper_te_st_name
index 198f1b13a37b0081f66d2d10be92293e57fb2ded..0caa362f5bd1bf4e359c529b87ab82cb1026df00 100644 (file)
@@ -84,5 +84,7 @@ void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
+                                   int is_write, int is_user, uintptr_t retaddr);
 
 #endif
index 7ec46b90fc4d0411f9706d236e8a8863f504fa71..2491f0a301c4c28e5ed37386ac8f3c26b64d63db 100644 (file)
@@ -292,6 +292,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
     cc->handle_mmu_fault = alpha_cpu_handle_mmu_fault;
 #else
     cc->do_unassigned_access = alpha_cpu_unassigned_access;
+    cc->do_unaligned_access = alpha_cpu_do_unaligned_access;
     cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
     dc->vmsd = &vmstate_alpha_cpu;
 #endif
index 07d9f63d1fd0583ec773ca7d80ceb09530224262..d9b861f40462f2c37a52a07720b0c124db0d9a91 100644 (file)
@@ -24,6 +24,7 @@
 #include "qemu-common.h"
 
 #define TARGET_LONG_BITS 64
+#define ALIGNED_ONLY
 
 #define CPUArchState struct CPUAlphaState
 
index ef6b7058cba057f701b2af91d0eef04300934d31..fc4f57a64478d17863a8dedaff60782b00ec8908 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "cpu.h"
 #include "exec/helper-proto.h"
-
+#include "exec/cpu_ldst.h"
 
 /* Softmmu support */
 #ifndef CONFIG_USER_ONLY
@@ -96,11 +96,11 @@ uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
     return ret;
 }
 
-static void do_unaligned_access(CPUAlphaState *env, target_ulong addr,
-                                int is_write, int is_user, uintptr_t retaddr)
+void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+                                   int is_write, int is_user, uintptr_t retaddr)
 {
-    AlphaCPU *cpu = alpha_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    AlphaCPU *cpu = ALPHA_CPU(cs);
+    CPUAlphaState *env = &cpu->env;
     uint64_t pc;
     uint32_t insn;
 
@@ -131,23 +131,6 @@ void alpha_cpu_unassigned_access(CPUState *cs, hwaddr addr,
     dynamic_excp(env, 0, EXCP_MCHK, 0);
 }
 
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 /* try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
index e31d56c629f9c78273709c765de1890cf30bc5d8..cc81e774df5d77d500d1ea6f52e65bed75161a96 100644 (file)
@@ -21,6 +21,7 @@
 #include "disas/disas.h"
 #include "qemu/host-utils.h"
 #include "tcg-op.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
diff --git a/target-arm/arm_ldst.h b/target-arm/arm_ldst.h
new file mode 100644 (file)
index 0000000..b1ece01
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * ARM load/store instructions for code (armeb-user support)
+ *
+ *  Copyright (c) 2012 CodeSourcery, LLC
+ *
+ * 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/>.
+ */
+
+#ifndef ARM_LDST_H
+#define ARM_LDST_H
+
+#include "exec/cpu_ldst.h"
+#include "qemu/bswap.h"
+
+/* Load an instruction and return it in the standard little-endian order */
+static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
+                                    bool do_swap)
+{
+    uint32_t insn = cpu_ldl_code(env, addr);
+    if (do_swap) {
+        return bswap32(insn);
+    }
+    return insn;
+}
+
+/* Ditto, for a halfword (Thumb) instruction */
+static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
+                                     bool do_swap)
+{
+    uint16_t insn = cpu_lduw_code(env, addr);
+    if (do_swap) {
+        return bswap16(insn);
+    }
+    return insn;
+}
+
+#endif
index 8d04385261219d9b1f5a02198a441b90785a009a..7d8332e8be20ebf0fc87a7d6480aa15bcf414834 100644 (file)
@@ -1199,26 +1199,4 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
     }
 }
 
-/* Load an instruction and return it in the standard little-endian order */
-static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
-                                    bool do_swap)
-{
-    uint32_t insn = cpu_ldl_code(env, addr);
-    if (do_swap) {
-        return bswap32(insn);
-    }
-    return insn;
-}
-
-/* Ditto, for a halfword (Thumb) instruction */
-static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
-                                     bool do_swap)
-{
-    uint16_t insn = cpu_lduw_code(env, addr);
-    if (do_swap) {
-        return bswap16(insn);
-    }
-    return insn;
-}
-
 #endif
index ec031f59472af961052ff51288bb60db542bd2e4..95af6241265323cde87b8d644faa785fe696d1ec 100644 (file)
@@ -7,11 +7,11 @@
 #include "sysemu/sysemu.h"
 #include "qemu/bitops.h"
 #include "qemu/crc32c.h"
+#include "exec/cpu_ldst.h"
+#include "arm_ldst.h"
 #include <zlib.h> /* For crc32 */
 
 #ifndef CONFIG_USER_ONLY
-#include "exec/softmmu_exec.h"
-
 static inline int get_phys_addr(CPUARMState *env, target_ulong address,
                                 int access_type, int is_user,
                                 hwaddr *phys_ptr, int *prot,
index b28f694d0010e7c190f72f8046ca78046c9cea14..9c1ef525a3966ba82aaa645e68132e62fc9fa2b1 100644 (file)
@@ -19,6 +19,7 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "internals.h"
+#include "exec/cpu_ldst.h"
 
 #define SIGNBIT (uint32_t)0x80000000
 #define SIGNBIT64 ((uint64_t)1 << 63)
@@ -56,22 +57,6 @@ uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
 
 #if !defined(CONFIG_USER_ONLY)
 
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 /* try to fill the TLB and return an exception if error. If retaddr is
  * NULL, it means that the function was called in C code (i.e. not
  * from generated code or from helper.c)
index 9f964dfd5de5860e23ba66ba3560b44bf9b67ab1..a9c4633517b459aa46bb10a9d722e93ce35b2133 100644 (file)
@@ -25,6 +25,7 @@
 #include "cpu.h"
 #include "tcg-op.h"
 #include "qemu/log.h"
+#include "arm_ldst.h"
 #include "translate.h"
 #include "internals.h"
 #include "qemu/host-utils.h"
index 7f6fcd699e232378ed8308d8d0f6c1685ae256e4..d499caa562324cab03386d5dd1902443f8d64b19 100644 (file)
@@ -30,6 +30,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "qemu/bitops.h"
+#include "arm_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index 4092d279ba8a685b87aba4dff78d0805a99ef1dc..e8b8261fe9e258254eec0c838b1954751e7d2e50 100644 (file)
@@ -21,6 +21,7 @@
 #include "cpu.h"
 #include "mmu.h"
 #include "qemu/host-utils.h"
+#include "exec/cpu_ldst.h"
 
 
 //#define CRIS_HELPER_DEBUG
index a9bd742d3b32e8d5dcba14fb701eeef16376fd2e..5c0c14d9928f5fb5a8e616f72ef1f8933e2cc03f 100644 (file)
@@ -22,6 +22,7 @@
 #include "mmu.h"
 #include "exec/helper-proto.h"
 #include "qemu/host-utils.h"
+#include "exec/cpu_ldst.h"
 
 //#define CRIS_OP_HELPER_DEBUG
 
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 /* Try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
index 90fe0a24b52c75edebaafe225b7174dcc39f15b0..ab0e47962bb4fc883d187af4efc1053b61ed183f 100644 (file)
@@ -28,6 +28,7 @@
 #include "tcg-op.h"
 #include "exec/helper-proto.h"
 #include "mmu.h"
+#include "exec/cpu_ldst.h"
 #include "crisv32-decode.h"
 
 #include "exec/helper-gen.h"
@@ -159,39 +160,9 @@ static int preg_sizes[] = {
 };
 
 #define t_gen_mov_TN_env(tn, member) \
_t_gen_mov_TN_env((tn), offsetof(CPUCRISState, member))
   tcg_gen_ld_tl(tn, cpu_env, offsetof(CPUCRISState, member))
 #define t_gen_mov_env_TN(member, tn) \
- _t_gen_mov_env_TN(offsetof(CPUCRISState, member), (tn))
-
-static inline void t_gen_mov_TN_reg(TCGv tn, int r)
-{
-    if (r < 0 || r > 15) {
-        fprintf(stderr, "wrong register read $r%d\n", r);
-    }
-    tcg_gen_mov_tl(tn, cpu_R[r]);
-}
-static inline void t_gen_mov_reg_TN(int r, TCGv tn)
-{
-    if (r < 0 || r > 15) {
-        fprintf(stderr, "wrong register write $r%d\n", r);
-    }
-    tcg_gen_mov_tl(cpu_R[r], tn);
-}
-
-static inline void _t_gen_mov_TN_env(TCGv tn, int offset)
-{
-    if (offset > sizeof(CPUCRISState)) {
-        fprintf(stderr, "wrong load from env from off=%d\n", offset);
-    }
-    tcg_gen_ld_tl(tn, cpu_env, offset);
-}
-static inline void _t_gen_mov_env_TN(int offset, TCGv tn)
-{
-    if (offset > sizeof(CPUCRISState)) {
-        fprintf(stderr, "wrong store to env at off=%d\n", offset);
-    }
-    tcg_gen_st_tl(tn, cpu_env, offset);
-}
+    tcg_gen_st_tl(tn, cpu_env, offsetof(CPUCRISState, member))
 
 static inline void t_gen_mov_TN_preg(TCGv tn, int r)
 {
@@ -1811,7 +1782,7 @@ static int dec_swap_r(CPUCRISState *env, DisasContext *dc)
 
     cris_cc_mask(dc, CC_MASK_NZ);
     t0 = tcg_temp_new();
-    t_gen_mov_TN_reg(t0, dc->op1);
+    tcg_gen_mov_tl(t0, cpu_R[dc->op1]);
     if (dc->op2 & 8) {
         tcg_gen_not_tl(t0, t0);
     }
@@ -2119,7 +2090,7 @@ static int dec_move_rp(CPUCRISState *env, DisasContext *dc)
     t[0] = tcg_temp_new();
     if (dc->op2 == PR_CCS) {
         cris_evaluate_flags(dc);
-        t_gen_mov_TN_reg(t[0], dc->op1);
+        tcg_gen_mov_tl(t[0], cpu_R[dc->op1]);
         if (dc->tb_flags & U_FLAG) {
             t[1] = tcg_temp_new();
             /* User space is not allowed to touch all flags.  */
@@ -2129,7 +2100,7 @@ static int dec_move_rp(CPUCRISState *env, DisasContext *dc)
             tcg_temp_free(t[1]);
         }
     } else {
-        t_gen_mov_TN_reg(t[0], dc->op1);
+        tcg_gen_mov_tl(t[0], cpu_R[dc->op1]);
     }
 
     t_gen_mov_preg_TN(dc, dc->op2, t[0]);
index 2ad2b142a9f54282249f51088e7a747a5f6d34a0..efb3639a06d3a8297c89b032c01b98b6194feef0 100644 (file)
@@ -516,7 +516,7 @@ static void dec10_reg_swap(DisasContext *dc)
 
     cris_cc_mask(dc, CC_MASK_NZVC);
     t0 = tcg_temp_new();
-    t_gen_mov_TN_reg(t0, dc->src);
+    tcg_gen_mov_tl(t0, cpu_R[dc->src]);
     if (dc->dst & 8)
         tcg_gen_not_tl(t0, t0);
     if (dc->dst & 4)
index e9b3d577b3d8b76314405016119cd92defffe9f5..0808cfc67df5db460ba2e28d83c3b54ecbe1c767 100644 (file)
@@ -87,6 +87,7 @@ typedef struct X86CPU {
     bool hyperv_time;
     bool check_cpuid;
     bool enforce_cpuid;
+    bool expose_kvm;
 
     /* if true the CPUID code directly forward host cache leaves to the guest */
     bool cache_info_passthrough;
index 042a48d70301c6659a7dd456056e3935ff3e08f2..dde052cc4266b514d432f6b757ddc56016af97d8 100644 (file)
@@ -552,8 +552,7 @@ struct X86CPUDefinition {
           CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
           CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
           /* partly implemented:
-          CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64)
-          CPUID_PSE36 (needed for Solaris) */
+          CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) */
           /* missing:
           CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
 #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | \
@@ -569,9 +568,7 @@ struct X86CPUDefinition {
           CPUID_EXT_RDRAND */
 #define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
           CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
-          CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
-          /* missing:
-          CPUID_EXT2_PDPE1GB */
+          CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB)
 #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
           CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
 #define TCG_SVM_FEATURES 0
@@ -2792,6 +2789,7 @@ static Property x86_cpu_properties[] = {
     DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
     DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, false),
     DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
+    DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
     DEFINE_PROP_END_OF_LIST()
 };
 
index e9cbdabc0385680f1e2c711cda9b3a6a64568946..b5e1b411fb7aeec5d7d03701cb24d7d3e5e92a0a 100644 (file)
 #define PG_DIRTY_BIT    6
 #define PG_PSE_BIT      7
 #define PG_GLOBAL_BIT   8
+#define PG_PSE_PAT_BIT  12
 #define PG_NX_BIT       63
 
 #define PG_PRESENT_MASK  (1 << PG_PRESENT_BIT)
 #define PG_DIRTY_MASK    (1 << PG_DIRTY_BIT)
 #define PG_PSE_MASK      (1 << PG_PSE_BIT)
 #define PG_GLOBAL_MASK   (1 << PG_GLOBAL_BIT)
+#define PG_PSE_PAT_MASK  (1 << PG_PSE_PAT_BIT)
+#define PG_ADDRESS_MASK  0x000ffffffffff000LL
+#define PG_HI_RSVD_MASK  (PG_ADDRESS_MASK & ~PHYS_ADDR_MASK)
 #define PG_HI_USER_MASK  0x7ff0000000000000LL
 #define PG_NX_MASK       (1LL << PG_NX_BIT)
 
@@ -986,7 +990,6 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
     /* update the hidden flags */
     {
         if (seg_reg == R_CS) {
-            int cpl = selector & 3;
 #ifdef TARGET_X86_64
             if ((env->hflags & HF_LMA_MASK) && (flags & DESC_L_MASK)) {
                 /* long mode */
@@ -996,15 +999,14 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
 #endif
             {
                 /* legacy / compatibility case */
-                if (!(env->cr[0] & CR0_PE_MASK))
-                    cpl = 0;
-                else if (env->eflags & VM_MASK)
-                    cpl = 3;
                 new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
                     >> (DESC_B_SHIFT - HF_CS32_SHIFT);
                 env->hflags = (env->hflags & ~(HF_CS32_MASK | HF_CS64_MASK)) |
                     new_hflags;
             }
+        }
+        if (seg_reg == R_SS) {
+            int cpl = (flags >> DESC_DPL_SHIFT) & 3;
 #if HF_CPL_MASK != 3
 #error HF_CPL_MASK is hardcoded
 #endif
@@ -1137,6 +1139,14 @@ uint64_t cpu_get_tsc(CPUX86State *env);
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
 
+/* XXX: This value should match the one returned by CPUID
+ * and in exec.c */
+# if defined(TARGET_X86_64)
+# define PHYS_ADDR_MASK 0xffffffffffLL
+# else
+# define PHYS_ADDR_MASK 0xfffffffffLL
+# endif
+
 static inline CPUX86State *cpu_init(const char *cpu_model)
 {
     X86CPU *cpu = cpu_x86_init(cpu_model);
@@ -1153,17 +1163,24 @@ static inline CPUX86State *cpu_init(const char *cpu_model)
 #define cpudef_setup x86_cpudef_setup
 
 /* MMU modes definitions */
-#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE0_SUFFIX _ksmap
 #define MMU_MODE1_SUFFIX _user
-#define MMU_MODE2_SUFFIX _ksmap /* Kernel with SMAP override */
-#define MMU_KERNEL_IDX  0
+#define MMU_MODE2_SUFFIX _knosmap /* SMAP disabled or CPL<3 && AC=1 */
+#define MMU_KSMAP_IDX   0
 #define MMU_USER_IDX    1
-#define MMU_KSMAP_IDX   2
-static inline int cpu_mmu_index (CPUX86State *env)
+#define MMU_KNOSMAP_IDX 2
+static inline int cpu_mmu_index(CPUX86State *env)
 {
     return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX :
-        ((env->hflags & HF_SMAP_MASK) && (env->eflags & AC_MASK))
-        ? MMU_KSMAP_IDX : MMU_KERNEL_IDX;
+        (!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK))
+        ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
+}
+
+static inline int cpu_mmu_index_kernel(CPUX86State *env)
+{
+    return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX :
+        ((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK))
+        ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX;
 }
 
 #define CC_DST  (env->cc_dst)
@@ -1234,11 +1251,14 @@ static inline uint32_t cpu_compute_eflags(CPUX86State *env)
     return env->eflags | cpu_cc_compute_all(env, CC_OP) | (env->df & DF_MASK);
 }
 
-/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
+/* NOTE: the translator must set DisasContext.cc_op to CC_OP_EFLAGS
+ * after generating a call to a helper that uses this.
+ */
 static inline void cpu_load_eflags(CPUX86State *env, int eflags,
                                    int update_mask)
 {
     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+    CC_OP = CC_OP_EFLAGS;
     env->df = 1 - (2 * ((eflags >> 10) & 1));
     env->eflags = (env->eflags & ~update_mask) |
         (eflags & update_mask) | 0x2;
index a04e754e61cd5f35db219534045e58344187f82d..1b2900d5d2f0d07eb6aa10ef7d72d6b31bd84cc9 100644 (file)
 #include "exec/helper-proto.h"
 #include "qemu/aes.h"
 #include "qemu/host-utils.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
+#include "exec/cpu_ldst.h"
 
 #define FPU_RC_MASK         0xc00
 #define FPU_RC_NEAR         0x000
index d34e5355f799404e88a3cbbb2b5418b61f3be31f..19fe9adc3f3c2b7470bd41811416e75c161494f0 100644 (file)
@@ -127,9 +127,11 @@ static int x86_cpu_gdb_load_seg(X86CPU *cpu, int sreg, uint8_t *mem_buf)
         target_ulong base;
 
         if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
+            int dpl = (env->eflags & VM_MASK) ? 3 : 0;
             base = selector << 4;
             limit = 0xffff;
-            flags = 0;
+            flags = DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                    DESC_A_MASK | (dpl << DESC_DPL_SHIFT);
         } else {
             if (!cpu_x86_get_descr_debug(env, selector, &base, &limit,
                                          &flags)) {
index 46d20e4b8952fc6f8f42d6d11f37d4221eb7c29d..11ca8649b5c1d8054a52e6a2a0eb2c2eb2f937ba 100644 (file)
@@ -510,14 +510,6 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
 
 #else
 
-/* XXX: This value should match the one returned by CPUID
- * and in exec.c */
-# if defined(TARGET_X86_64)
-# define PHYS_ADDR_MASK 0xfffffff000LL
-# else
-# define PHYS_ADDR_MASK 0xffffff000LL
-# endif
-
 /* return value:
  * -1 = cannot handle fault
  * 0  = nothing more to do
@@ -530,10 +522,12 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
     CPUX86State *env = &cpu->env;
     uint64_t ptep, pte;
     target_ulong pde_addr, pte_addr;
-    int error_code, is_dirty, prot, page_size, is_write, is_user;
+    int error_code = 0;
+    int is_dirty, prot, page_size, is_write, is_user;
     hwaddr paddr;
+    uint64_t rsvd_mask = PG_HI_RSVD_MASK;
     uint32_t page_offset;
-    target_ulong vaddr, virt_addr;
+    target_ulong vaddr;
 
     is_user = mmu_idx == MMU_USER_IDX;
 #if defined(DEBUG_MMU)
@@ -550,12 +544,15 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
             pte = (uint32_t)pte;
         }
 #endif
-        virt_addr = addr & TARGET_PAGE_MASK;
         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
         page_size = 4096;
         goto do_mapping;
     }
 
+    if (!(env->efer & MSR_EFER_NXE)) {
+        rsvd_mask |= PG_NX_MASK;
+    }
+
     if (env->cr[4] & CR4_PAE_MASK) {
         uint64_t pde, pdpe;
         target_ulong pdpe_addr;
@@ -577,34 +574,37 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
                 env->a20_mask;
             pml4e = ldq_phys(cs->as, pml4e_addr);
             if (!(pml4e & PG_PRESENT_MASK)) {
-                error_code = 0;
                 goto do_fault;
             }
-            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
-                error_code = PG_ERROR_RSVD_MASK;
-                goto do_fault;
+            if (pml4e & (rsvd_mask | PG_PSE_MASK)) {
+                goto do_fault_rsvd;
             }
             if (!(pml4e & PG_ACCESSED_MASK)) {
                 pml4e |= PG_ACCESSED_MASK;
                 stl_phys_notdirty(cs->as, pml4e_addr, pml4e);
             }
             ptep = pml4e ^ PG_NX_MASK;
-            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
+            pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
                 env->a20_mask;
             pdpe = ldq_phys(cs->as, pdpe_addr);
             if (!(pdpe & PG_PRESENT_MASK)) {
-                error_code = 0;
                 goto do_fault;
             }
-            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
-                error_code = PG_ERROR_RSVD_MASK;
-                goto do_fault;
+            if (pdpe & rsvd_mask) {
+                goto do_fault_rsvd;
             }
             ptep &= pdpe ^ PG_NX_MASK;
             if (!(pdpe & PG_ACCESSED_MASK)) {
                 pdpe |= PG_ACCESSED_MASK;
                 stl_phys_notdirty(cs->as, pdpe_addr, pdpe);
             }
+            if (pdpe & PG_PSE_MASK) {
+                /* 1 GB page */
+                page_size = 1024 * 1024 * 1024;
+                pte_addr = pdpe_addr;
+                pte = pdpe;
+                goto do_check_protect;
+            }
         } else
 #endif
         {
@@ -613,134 +613,49 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
                 env->a20_mask;
             pdpe = ldq_phys(cs->as, pdpe_addr);
             if (!(pdpe & PG_PRESENT_MASK)) {
-                error_code = 0;
                 goto do_fault;
             }
+            rsvd_mask |= PG_HI_USER_MASK | PG_NX_MASK;
+            if (pdpe & rsvd_mask) {
+                goto do_fault_rsvd;
+            }
             ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
         }
 
-        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
+        pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
             env->a20_mask;
         pde = ldq_phys(cs->as, pde_addr);
         if (!(pde & PG_PRESENT_MASK)) {
-            error_code = 0;
             goto do_fault;
         }
-        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
-            error_code = PG_ERROR_RSVD_MASK;
-            goto do_fault;
+        if (pde & rsvd_mask) {
+            goto do_fault_rsvd;
         }
         ptep &= pde ^ PG_NX_MASK;
         if (pde & PG_PSE_MASK) {
             /* 2 MB page */
             page_size = 2048 * 1024;
-            ptep ^= PG_NX_MASK;
-            if ((ptep & PG_NX_MASK) && is_write1 == 2) {
-                goto do_fault_protect;
-            }
-            switch (mmu_idx) {
-            case MMU_USER_IDX:
-                if (!(ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if (is_write && !(ptep & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
-
-            case MMU_KERNEL_IDX:
-                if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) &&
-                    (ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                /* fall through */
-            case MMU_KSMAP_IDX:
-                if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) &&
-                    (ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if ((env->cr[0] & CR0_WP_MASK) &&
-                    is_write && !(ptep & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
-
-            default: /* cannot happen */
-                break;
-            }
-            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
-            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
-                pde |= PG_ACCESSED_MASK;
-                if (is_dirty)
-                    pde |= PG_DIRTY_MASK;
-                stl_phys_notdirty(cs->as, pde_addr, pde);
-            }
-            /* align to page_size */
-            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
-            virt_addr = addr & ~(page_size - 1);
-        } else {
-            /* 4 KB page */
-            if (!(pde & PG_ACCESSED_MASK)) {
-                pde |= PG_ACCESSED_MASK;
-                stl_phys_notdirty(cs->as, pde_addr, pde);
-            }
-            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
-                env->a20_mask;
-            pte = ldq_phys(cs->as, pte_addr);
-            if (!(pte & PG_PRESENT_MASK)) {
-                error_code = 0;
-                goto do_fault;
-            }
-            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
-                error_code = PG_ERROR_RSVD_MASK;
-                goto do_fault;
-            }
-            /* combine pde and pte nx, user and rw protections */
-            ptep &= pte ^ PG_NX_MASK;
-            ptep ^= PG_NX_MASK;
-            if ((ptep & PG_NX_MASK) && is_write1 == 2)
-                goto do_fault_protect;
-            switch (mmu_idx) {
-            case MMU_USER_IDX:
-                if (!(ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if (is_write && !(ptep & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
-
-            case MMU_KERNEL_IDX:
-                if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) &&
-                    (ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                /* fall through */
-            case MMU_KSMAP_IDX:
-                if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) &&
-                    (ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if ((env->cr[0] & CR0_WP_MASK) &&
-                    is_write && !(ptep & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
-
-            default: /* cannot happen */
-                break;
-            }
-            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
-            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
-                pte |= PG_ACCESSED_MASK;
-                if (is_dirty)
-                    pte |= PG_DIRTY_MASK;
-                stl_phys_notdirty(cs->as, pte_addr, pte);
-            }
-            page_size = 4096;
-            virt_addr = addr & ~0xfff;
-            pte = pte & (PHYS_ADDR_MASK | 0xfff);
+            pte_addr = pde_addr;
+            pte = pde;
+            goto do_check_protect;
+        }
+        /* 4 KB page */
+        if (!(pde & PG_ACCESSED_MASK)) {
+            pde |= PG_ACCESSED_MASK;
+            stl_phys_notdirty(cs->as, pde_addr, pde);
+        }
+        pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
+            env->a20_mask;
+        pte = ldq_phys(cs->as, pte_addr);
+        if (!(pte & PG_PRESENT_MASK)) {
+            goto do_fault;
+        }
+        if (pte & rsvd_mask) {
+            goto do_fault_rsvd;
         }
+        /* combine pde and pte nx, user and rw protections */
+        ptep &= pte ^ PG_NX_MASK;
+        page_size = 4096;
     } else {
         uint32_t pde;
 
@@ -749,114 +664,95 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
             env->a20_mask;
         pde = ldl_phys(cs->as, pde_addr);
         if (!(pde & PG_PRESENT_MASK)) {
-            error_code = 0;
             goto do_fault;
         }
+        ptep = pde | PG_NX_MASK;
+
         /* if PSE bit is set, then we use a 4MB page */
         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
             page_size = 4096 * 1024;
-            switch (mmu_idx) {
-            case MMU_USER_IDX:
-                if (!(pde & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if (is_write && !(pde & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
-
-            case MMU_KERNEL_IDX:
-                if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) &&
-                    (pde & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                /* fall through */
-            case MMU_KSMAP_IDX:
-                if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) &&
-                    (pde & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if ((env->cr[0] & CR0_WP_MASK) &&
-                    is_write && !(pde & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
+            pte_addr = pde_addr;
+
+            /* Bits 20-13 provide bits 39-32 of the address, bit 21 is reserved.
+             * Leave bits 20-13 in place for setting accessed/dirty bits below.
+             */
+            pte = pde | ((pde & 0x1fe000) << (32 - 13));
+            rsvd_mask = 0x200000;
+            goto do_check_protect_pse36;
+        }
 
-            default: /* cannot happen */
-                break;
-            }
-            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
-            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
-                pde |= PG_ACCESSED_MASK;
-                if (is_dirty)
-                    pde |= PG_DIRTY_MASK;
-                stl_phys_notdirty(cs->as, pde_addr, pde);
-            }
+        if (!(pde & PG_ACCESSED_MASK)) {
+            pde |= PG_ACCESSED_MASK;
+            stl_phys_notdirty(cs->as, pde_addr, pde);
+        }
 
-            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
-            ptep = pte;
-            virt_addr = addr & ~(page_size - 1);
-        } else {
-            if (!(pde & PG_ACCESSED_MASK)) {
-                pde |= PG_ACCESSED_MASK;
-                stl_phys_notdirty(cs->as, pde_addr, pde);
-            }
+        /* page directory entry */
+        pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
+            env->a20_mask;
+        pte = ldl_phys(cs->as, pte_addr);
+        if (!(pte & PG_PRESENT_MASK)) {
+            goto do_fault;
+        }
+        /* combine pde and pte user and rw protections */
+        ptep &= pte | PG_NX_MASK;
+        page_size = 4096;
+        rsvd_mask = 0;
+    }
 
-            /* page directory entry */
-            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
-                env->a20_mask;
-            pte = ldl_phys(cs->as, pte_addr);
-            if (!(pte & PG_PRESENT_MASK)) {
-                error_code = 0;
-                goto do_fault;
-            }
-            /* combine pde and pte user and rw protections */
-            ptep = pte & pde;
-            switch (mmu_idx) {
-            case MMU_USER_IDX:
-                if (!(ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if (is_write && !(ptep & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
+do_check_protect:
+    rsvd_mask |= (page_size - 1) & PG_ADDRESS_MASK & ~PG_PSE_PAT_MASK;
+do_check_protect_pse36:
+    if (pte & rsvd_mask) {
+        goto do_fault_rsvd;
+    }
+    ptep ^= PG_NX_MASK;
+    if ((ptep & PG_NX_MASK) && is_write1 == 2) {
+        goto do_fault_protect;
+    }
+    switch (mmu_idx) {
+    case MMU_USER_IDX:
+        if (!(ptep & PG_USER_MASK)) {
+            goto do_fault_protect;
+        }
+        if (is_write && !(ptep & PG_RW_MASK)) {
+            goto do_fault_protect;
+        }
+        break;
 
-            case MMU_KERNEL_IDX:
-                if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) &&
-                    (ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                /* fall through */
-            case MMU_KSMAP_IDX:
-                if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) &&
-                    (ptep & PG_USER_MASK)) {
-                    goto do_fault_protect;
-                }
-                if ((env->cr[0] & CR0_WP_MASK) &&
-                    is_write && !(ptep & PG_RW_MASK)) {
-                    goto do_fault_protect;
-                }
-                break;
+    case MMU_KSMAP_IDX:
+        if (is_write1 != 2 && (ptep & PG_USER_MASK)) {
+            goto do_fault_protect;
+        }
+        /* fall through */
+    case MMU_KNOSMAP_IDX:
+        if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) &&
+            (ptep & PG_USER_MASK)) {
+            goto do_fault_protect;
+        }
+        if ((env->cr[0] & CR0_WP_MASK) &&
+            is_write && !(ptep & PG_RW_MASK)) {
+            goto do_fault_protect;
+        }
+        break;
 
-            default: /* cannot happen */
-                break;
-            }
-            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
-            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
-                pte |= PG_ACCESSED_MASK;
-                if (is_dirty)
-                    pte |= PG_DIRTY_MASK;
-                stl_phys_notdirty(cs->as, pte_addr, pte);
-            }
-            page_size = 4096;
-            virt_addr = addr & ~0xfff;
+    default: /* cannot happen */
+        break;
+    }
+    is_dirty = is_write && !(pte & PG_DIRTY_MASK);
+    if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
+        pte |= PG_ACCESSED_MASK;
+        if (is_dirty) {
+            pte |= PG_DIRTY_MASK;
         }
+        stl_phys_notdirty(cs->as, pte_addr, pte);
     }
+
     /* the page can be put in the TLB */
     prot = PAGE_READ;
-    if (!(ptep & PG_NX_MASK))
+    if (!(ptep & PG_NX_MASK) &&
+        !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK))) {
         prot |= PAGE_EXEC;
+    }
     if (pte & PG_DIRTY_MASK) {
         /* only set write access if already dirty... otherwise wait
            for dirty access */
@@ -872,16 +768,21 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
  do_mapping:
     pte = pte & env->a20_mask;
 
+    /* align to page_size */
+    pte &= PG_ADDRESS_MASK & ~(page_size - 1);
+
     /* Even if 4MB pages, we map only one 4KB page in the cache to
        avoid filling it too fast */
-    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
-    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
-    vaddr = virt_addr + page_offset;
+    vaddr = addr & TARGET_PAGE_MASK;
+    page_offset = vaddr & (page_size - 1);
+    paddr = pte + page_offset;
 
     tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
     return 0;
+ do_fault_rsvd:
+    error_code |= PG_ERROR_RSVD_MASK;
  do_fault_protect:
-    error_code = PG_ERROR_P_MASK;
+    error_code |= PG_ERROR_P_MASK;
  do_fault:
     error_code |= (is_write << PG_ERROR_W_BIT);
     if (is_user)
@@ -910,7 +811,6 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     CPUX86State *env = &cpu->env;
     target_ulong pde_addr, pte_addr;
     uint64_t pte;
-    hwaddr paddr;
     uint32_t page_offset;
     int page_size;
 
@@ -928,25 +828,24 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 
             /* test virtual address sign extension */
             sext = (int64_t)addr >> 47;
-            if (sext != 0 && sext != -1)
+            if (sext != 0 && sext != -1) {
                 return -1;
-
+            }
             pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
                 env->a20_mask;
             pml4e = ldq_phys(cs->as, pml4e_addr);
-            if (!(pml4e & PG_PRESENT_MASK))
+            if (!(pml4e & PG_PRESENT_MASK)) {
                 return -1;
-
-            pdpe_addr = ((pml4e & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+            }
+            pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
                          (((addr >> 30) & 0x1ff) << 3)) & env->a20_mask;
             pdpe = ldq_phys(cs->as, pdpe_addr);
-            if (!(pdpe & PG_PRESENT_MASK))
+            if (!(pdpe & PG_PRESENT_MASK)) {
                 return -1;
-
+            }
             if (pdpe & PG_PSE_MASK) {
                 page_size = 1024 * 1024 * 1024;
-                pte = pdpe & ~( (page_size - 1) & ~0xfff);
-                pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
+                pte = pdpe;
                 goto out;
             }
 
@@ -960,7 +859,7 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
                 return -1;
         }
 
-        pde_addr = ((pdpe & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+        pde_addr = ((pdpe & PG_ADDRESS_MASK) +
                     (((addr >> 21) & 0x1ff) << 3)) & env->a20_mask;
         pde = ldq_phys(cs->as, pde_addr);
         if (!(pde & PG_PRESENT_MASK)) {
@@ -969,17 +868,17 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         if (pde & PG_PSE_MASK) {
             /* 2 MB page */
             page_size = 2048 * 1024;
-            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
+            pte = pde;
         } else {
             /* 4 KB page */
-            pte_addr = ((pde & ~0xfff & ~(PG_NX_MASK | PG_HI_USER_MASK)) +
+            pte_addr = ((pde & PG_ADDRESS_MASK) +
                         (((addr >> 12) & 0x1ff) << 3)) & env->a20_mask;
             page_size = 4096;
             pte = ldq_phys(cs->as, pte_addr);
         }
-        pte &= ~(PG_NX_MASK | PG_HI_USER_MASK);
-        if (!(pte & PG_PRESENT_MASK))
+        if (!(pte & PG_PRESENT_MASK)) {
             return -1;
+        }
     } else {
         uint32_t pde;
 
@@ -989,14 +888,15 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
         if (!(pde & PG_PRESENT_MASK))
             return -1;
         if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
-            pte = pde & ~0x003ff000; /* align to 4MB */
+            pte = pde | ((pde & 0x1fe000) << (32 - 13));
             page_size = 4096 * 1024;
         } else {
             /* page directory entry */
             pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
             pte = ldl_phys(cs->as, pte_addr);
-            if (!(pte & PG_PRESENT_MASK))
+            if (!(pte & PG_PRESENT_MASK)) {
                 return -1;
+            }
             page_size = 4096;
         }
         pte = pte & env->a20_mask;
@@ -1005,9 +905,9 @@ hwaddr x86_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 #ifdef TARGET_X86_64
 out:
 #endif
+    pte &= PG_ADDRESS_MASK & ~(page_size - 1);
     page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
-    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
-    return paddr;
+    return pte | page_offset;
 }
 
 void hw_breakpoint_insert(CPUX86State *env, int index)
index 0d894ef4aaef979c6b4f5a08bb53cca2c03b2cfe..4bf0ac9e76a082e43a1c58c86c5431ee01e16d93 100644 (file)
@@ -528,23 +528,25 @@ int kvm_arch_init_vcpu(CPUState *cs)
         has_msr_hv_hypercall = true;
     }
 
-    memcpy(signature, "KVMKVMKVM\0\0\0", 12);
-    c = &cpuid_data.entries[cpuid_i++];
-    c->function = KVM_CPUID_SIGNATURE | kvm_base;
-    c->eax = 0;
-    c->ebx = signature[0];
-    c->ecx = signature[1];
-    c->edx = signature[2];
+    if (cpu->expose_kvm) {
+        memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+        c = &cpuid_data.entries[cpuid_i++];
+        c->function = KVM_CPUID_SIGNATURE | kvm_base;
+        c->eax = KVM_CPUID_FEATURES | kvm_base;
+        c->ebx = signature[0];
+        c->ecx = signature[1];
+        c->edx = signature[2];
 
-    c = &cpuid_data.entries[cpuid_i++];
-    c->function = KVM_CPUID_FEATURES | kvm_base;
-    c->eax = env->features[FEAT_KVM];
+        c = &cpuid_data.entries[cpuid_i++];
+        c->function = KVM_CPUID_FEATURES | kvm_base;
+        c->eax = env->features[FEAT_KVM];
 
-    has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
+        has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
 
-    has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI);
+        has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI);
 
-    has_msr_kvm_steal_time = c->eax & (1 << KVM_FEATURE_STEAL_TIME);
+        has_msr_kvm_steal_time = c->eax & (1 << KVM_FEATURE_STEAL_TIME);
+    }
 
     cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
 
@@ -1430,7 +1432,7 @@ static int kvm_get_sregs(X86CPU *cpu)
        HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
        HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
 
-    hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
+    hflags = (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
     hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
     hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
                 (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
index 168cab681b8a4fe13f69acf824c562a8e1872929..bdff44778617cdf35a28bae36dce502909402711 100644 (file)
@@ -312,6 +312,14 @@ static int cpu_post_load(void *opaque, int version_id)
         env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK);
     }
 
+    /* Older versions of QEMU incorrectly used CS.DPL as the CPL when
+     * running under KVM.  This is wrong for conforming code segments.
+     * Luckily, in our implementation the CPL field of hflags is redundant
+     * and we can get the right value from the SS descriptor privilege level.
+     */
+    env->hflags &= ~HF_CPL_MASK;
+    env->hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
+
     /* XXX: restore FPU round state */
     env->fpstt = (env->fpus_vmstate >> 11) & 7;
     env->fpus = env->fpus_vmstate & ~0x3800;
index 83aa1038d72e4590c989539a09b23e0be84565d7..1aec8a5f1914955ce096fde3ae09f4d46d74107d 100644 (file)
 
 #include "cpu.h"
 #include "exec/helper-proto.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
+#include "exec/cpu_ldst.h"
 
 /* broken thread support */
 
@@ -109,24 +106,6 @@ void helper_boundl(CPUX86State *env, target_ulong a0, int v)
     }
 }
 
-#if !defined(CONFIG_USER_ONLY)
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
-#endif
-
 #if !defined(CONFIG_USER_ONLY)
 /* try to fill the TLB and return an exception if error. If retaddr is
  * NULL, it means that the function was called in C code (i.e. not
index 9cfa25f9ec35165b9d51093d8a6aece3167c5c3f..4aaf1e4d95ee336d0e5034d04624825fab137ae3 100644 (file)
 #include "cpu.h"
 #include "exec/ioport.h"
 #include "exec/helper-proto.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-/* check if Port I/O is allowed in TSS */
-static inline void check_io(CPUX86State *env, int addr, int size)
-{
-    int io_offset, val, mask;
-
-    /* TSS must be a valid 32 bit one */
-    if (!(env->tr.flags & DESC_P_MASK) ||
-        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
-        env->tr.limit < 103) {
-        goto fail;
-    }
-    io_offset = cpu_lduw_kernel(env, env->tr.base + 0x66);
-    io_offset += (addr >> 3);
-    /* Note: the check needs two bytes */
-    if ((io_offset + 1) > env->tr.limit) {
-        goto fail;
-    }
-    val = cpu_lduw_kernel(env, env->tr.base + io_offset);
-    val >>= (addr & 7);
-    mask = (1 << size) - 1;
-    /* all bits must be zero to allow the I/O */
-    if ((val & mask) != 0) {
-    fail:
-        raise_exception_err(env, EXCP0D_GPF, 0);
-    }
-}
-
-void helper_check_iob(CPUX86State *env, uint32_t t0)
-{
-    check_io(env, t0, 1);
-}
-
-void helper_check_iow(CPUX86State *env, uint32_t t0)
-{
-    check_io(env, t0, 2);
-}
-
-void helper_check_iol(CPUX86State *env, uint32_t t0)
-{
-    check_io(env, t0, 4);
-}
+#include "exec/cpu_ldst.h"
 
 void helper_outb(uint32_t port, uint32_t data)
 {
index 258aae806a739252687cc36c8b57357e801dd0a7..2d970d0cb9c3f8a6f9eb33a4e813cc5c4974a5cb 100644 (file)
 #include "cpu.h"
 #include "qemu/log.h"
 #include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
 
 //#define DEBUG_PCALL
 
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
 #ifdef DEBUG_PCALL
 # define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
 # define LOG_PCALL_STATE(cpu)                                  \
 # define LOG_PCALL_STATE(cpu) do { } while (0)
 #endif
 
+#ifndef CONFIG_USER_ONLY
+#define CPU_MMU_INDEX (cpu_mmu_index_kernel(env))
+#define MEMSUFFIX _kernel
+#define DATA_SIZE 1
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 2
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 4
+#include "exec/cpu_ldst_template.h"
+
+#define DATA_SIZE 8
+#include "exec/cpu_ldst_template.h"
+#undef CPU_MMU_INDEX
+#undef MEMSUFFIX
+#endif
+
 /* return non zero if error */
 static inline int load_segment(CPUX86State *env, uint32_t *e1_ptr,
                                uint32_t *e2_ptr, int selector)
@@ -88,8 +103,10 @@ static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1,
 static inline void load_seg_vm(CPUX86State *env, int seg, int selector)
 {
     selector &= 0xffff;
-    cpu_x86_load_seg_cache(env, seg, selector,
-                           (selector << 4), 0xffff, 0);
+
+    cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK | (3 << DESC_DPL_SHIFT));
 }
 
 static inline void get_ss_esp_from_tss(CPUX86State *env, uint32_t *ss_ptr,
@@ -133,11 +150,10 @@ static inline void get_ss_esp_from_tss(CPUX86State *env, uint32_t *ss_ptr,
     }
 }
 
-/* XXX: merge with load_seg() */
-static void tss_load_seg(CPUX86State *env, int seg_reg, int selector)
+static void tss_load_seg(CPUX86State *env, int seg_reg, int selector, int cpl)
 {
     uint32_t e1, e2;
-    int rpl, dpl, cpl;
+    int rpl, dpl;
 
     if ((selector & 0xfffc) != 0) {
         if (load_segment(env, &e1, &e2, selector) != 0) {
@@ -148,18 +164,13 @@ static void tss_load_seg(CPUX86State *env, int seg_reg, int selector)
         }
         rpl = selector & 3;
         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
-        cpl = env->hflags & HF_CPL_MASK;
         if (seg_reg == R_CS) {
             if (!(e2 & DESC_CS_MASK)) {
                 raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
             }
-            /* XXX: is it correct? */
             if (dpl != rpl) {
                 raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
             }
-            if ((e2 & DESC_C_MASK) && dpl > rpl) {
-                raise_exception_err(env, EXCP0A_TSS, selector & 0xfffc);
-            }
         } else if (seg_reg == R_SS) {
             /* SS must be writable data */
             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) {
@@ -446,12 +457,13 @@ static void switch_tss(CPUX86State *env, int tss_selector,
 
     /* load the segments */
     if (!(new_eflags & VM_MASK)) {
-        tss_load_seg(env, R_CS, new_segs[R_CS]);
-        tss_load_seg(env, R_SS, new_segs[R_SS]);
-        tss_load_seg(env, R_ES, new_segs[R_ES]);
-        tss_load_seg(env, R_DS, new_segs[R_DS]);
-        tss_load_seg(env, R_FS, new_segs[R_FS]);
-        tss_load_seg(env, R_GS, new_segs[R_GS]);
+        int cpl = new_segs[R_CS] & 3;
+        tss_load_seg(env, R_CS, new_segs[R_CS], cpl);
+        tss_load_seg(env, R_SS, new_segs[R_SS], cpl);
+        tss_load_seg(env, R_ES, new_segs[R_ES], cpl);
+        tss_load_seg(env, R_DS, new_segs[R_DS], cpl);
+        tss_load_seg(env, R_FS, new_segs[R_FS], cpl);
+        tss_load_seg(env, R_GS, new_segs[R_GS], cpl);
     }
 
     /* check that env->eip is in the CS segment limits */
@@ -558,6 +570,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
     int has_error_code, new_stack, shift;
     uint32_t e1, e2, offset, ss = 0, esp, ss_e1 = 0, ss_e2 = 0;
     uint32_t old_eip, sp_mask;
+    int vm86 = env->eflags & VM_MASK;
 
     has_error_code = 0;
     if (!is_int && !is_hw) {
@@ -673,7 +686,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
         ssp = get_seg_base(ss_e1, ss_e2);
     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
         /* to same privilege */
-        if (env->eflags & VM_MASK) {
+        if (vm86) {
             raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);
         }
         new_stack = 0;
@@ -694,14 +707,14 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
 #if 0
     /* XXX: check that enough room is available */
     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
-    if (env->eflags & VM_MASK) {
+    if (vm86) {
         push_size += 8;
     }
     push_size <<= shift;
 #endif
     if (shift == 1) {
         if (new_stack) {
-            if (env->eflags & VM_MASK) {
+            if (vm86) {
                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
@@ -718,7 +731,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
         }
     } else {
         if (new_stack) {
-            if (env->eflags & VM_MASK) {
+            if (vm86) {
                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
@@ -742,7 +755,7 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
 
     if (new_stack) {
-        if (env->eflags & VM_MASK) {
+        if (vm86) {
             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
@@ -1600,7 +1613,6 @@ void helper_ljmp_protected(CPUX86State *env, int new_cs, target_ulong new_eip,
             }
             next_eip = env->eip + next_eip_addend;
             switch_tss(env, new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
-            CC_OP = CC_OP_EFLAGS;
             break;
         case 4: /* 286 call gate */
         case 12: /* 386 call gate */
@@ -1769,7 +1781,6 @@ void helper_lcall_protected(CPUX86State *env, int new_cs, target_ulong new_eip,
                 raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);
             }
             switch_tss(env, new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
-            CC_OP = CC_OP_EFLAGS;
             return;
         case 4: /* 286 call gate */
         case 12: /* 386 call gate */
@@ -2464,11 +2475,56 @@ void helper_verw(CPUX86State *env, target_ulong selector1)
 void cpu_x86_load_seg(CPUX86State *env, int seg_reg, int selector)
 {
     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
+        int dpl = (env->eflags & VM_MASK) ? 3 : 0;
         selector &= 0xffff;
         cpu_x86_load_seg_cache(env, seg_reg, selector,
-                               (selector << 4), 0xffff, 0);
+                               (selector << 4), 0xffff,
+                               DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                               DESC_A_MASK | (dpl << DESC_DPL_SHIFT));
     } else {
         helper_load_seg(env, seg_reg, selector);
     }
 }
 #endif
+
+/* check if Port I/O is allowed in TSS */
+static inline void check_io(CPUX86State *env, int addr, int size)
+{
+    int io_offset, val, mask;
+
+    /* TSS must be a valid 32 bit one */
+    if (!(env->tr.flags & DESC_P_MASK) ||
+        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
+        env->tr.limit < 103) {
+        goto fail;
+    }
+    io_offset = cpu_lduw_kernel(env, env->tr.base + 0x66);
+    io_offset += (addr >> 3);
+    /* Note: the check needs two bytes */
+    if ((io_offset + 1) > env->tr.limit) {
+        goto fail;
+    }
+    val = cpu_lduw_kernel(env, env->tr.base + io_offset);
+    val >>= (addr & 7);
+    mask = (1 << size) - 1;
+    /* all bits must be zero to allow the I/O */
+    if ((val & mask) != 0) {
+    fail:
+        raise_exception_err(env, EXCP0D_GPF, 0);
+    }
+}
+
+void helper_check_iob(CPUX86State *env, uint32_t t0)
+{
+    check_io(env, t0, 1);
+}
+
+void helper_check_iow(CPUX86State *env, uint32_t t0)
+{
+    check_io(env, t0, 2);
+}
+
+void helper_check_iol(CPUX86State *env, uint32_t t0)
+{
+    check_io(env, t0, 4);
+}
index 5d7697c1a707fd4cb307143424bb7470fb1dcbc0..58051d3bcc00c955cf84f89537591b012b942d9d 100644 (file)
@@ -168,15 +168,26 @@ void do_smm_enter(X86CPU *cpu)
                                       CR0_PG_MASK));
     cpu_x86_update_cr4(env, 0);
     env->dr[7] = 0x00000400;
-    CC_OP = CC_OP_EFLAGS;
 
     cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
-                           0xffffffff, 0);
-    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
-    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
-    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
-    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
-    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
+                           0xffffffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
+    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff,
+                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+                           DESC_A_MASK);
 }
 
 void helper_rsm(CPUX86State *env)
@@ -296,7 +307,6 @@ void helper_rsm(CPUX86State *env)
         env->smbase = ldl_phys(cs->as, sm_state + 0x7ef8) & ~0x7fff;
     }
 #endif
-    CC_OP = CC_OP_EFLAGS;
     env->hflags &= ~HF_SMM_MASK;
     cpu_smm_update(env);
 
index 852e2baf5dcef2c098d4ba241bce6100e602380d..429d029a3d9dfc94954804514b7e47f71e9d4534 100644 (file)
 #include "cpu.h"
 #include "exec/cpu-all.h"
 #include "exec/helper-proto.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
+#include "exec/cpu_ldst.h"
 
 /* Secure Virtual Machine helpers */
 
@@ -260,7 +257,6 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
                                   env->vm_vmcb + offsetof(struct vmcb,
                                                           save.rflags)),
                     ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
-    CC_OP = CC_OP_EFLAGS;
 
     svm_load_seg_cache(env, env->vm_vmcb + offsetof(struct vmcb, save.es),
                        R_ES);
@@ -702,7 +698,6 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
                                                            save.rflags)),
                     ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK |
                       VM_MASK));
-    CC_OP = CC_OP_EFLAGS;
 
     svm_load_seg_cache(env, env->vm_hsave + offsetof(struct vmcb, save.es),
                        R_ES);
index 3aa52eb795d9218b931e14a2dd4528c3bd1f3bd2..2359787b42b218960f6ebabea1daf02edc5d89c7 100644 (file)
@@ -27,6 +27,7 @@
 #include "cpu.h"
 #include "disas/disas.h"
 #include "tcg-op.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index 40fbed64c347dccc3f18d3dc8c2161ef083599c2..308742a74eadde8f475d0fdd6d98a17c6ec05c05 100644 (file)
@@ -6,23 +6,13 @@
 #include "hw/lm32/lm32_pic.h"
 #include "hw/char/lm32_juart.h"
 
-#include "exec/softmmu_exec.h"
+#include "exec/cpu_ldst.h"
 
 #ifndef CONFIG_USER_ONLY
 #include "sysemu/sysemu.h"
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
-#define MMUSUFFIX _mmu
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 void raise_exception(CPULM32State *env, int index)
 {
     CPUState *cs = CPU(lm32_env_get_cpu(env));
index 51eca06591275607559c7a0e9b01f07c4aff1eef..a51ade9a1566a45f32b02bc647061f6f2e40fb1e 100644 (file)
@@ -22,6 +22,7 @@
 #include "exec/helper-proto.h"
 #include "tcg-op.h"
 
+#include "exec/cpu_ldst.h"
 #include "hw/lm32/lm32_pic.h"
 
 #include "exec/helper-gen.h"
index f1ac139c51041524a8baf7c8996d770616887037..9dd3e74ab8c7e6e37c46bfc04a39833a5890b63f 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
 
 #if defined(CONFIG_USER_ONLY)
 
@@ -34,22 +35,6 @@ void do_interrupt_m68k_hardirq(CPUM68KState *env)
 
 extern int semihosting_enabled;
 
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 /* Try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
index fa248d96b53ffe3d9368726a2c143b3776a1b1b9..50df4d384411249770e753826b7858e191df4848 100644 (file)
@@ -22,6 +22,7 @@
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "qemu/log.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index b24b878919faaa22a369792c6fb58906cd14666c..a4c8f047057bc99387938f0e0062028feddce663 100644 (file)
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "qemu/host-utils.h"
+#include "exec/cpu_ldst.h"
 
 #define D(x)
 
 #if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-#define SHIFT 3
-#include "exec/softmmu_template.h"
 
 /* Try to fill the TLB and return an exception if error. If retaddr is
  * NULL, it means that the function was called in C code (i.e. not
index 488df2d60d533c589dc1caac9589685e2cf094ac..c422bdc71894202acd83979c460f9dc20e503e45 100644 (file)
@@ -23,6 +23,7 @@
 #include "tcg-op.h"
 #include "exec/helper-proto.h"
 #include "microblaze-decode.h"
+#include "exec/cpu_ldst.h"
 #include "exec/helper-gen.h"
 
 #define SIM_COMPAT 0
index 8877f813f7b5c25cdcd596554e5552efdb0f3e63..2cff15a27313d3cefdb796ada384959448616def 100644 (file)
@@ -80,5 +80,7 @@ void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
 hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
+                                  int is_write, int is_user, uintptr_t retaddr);
 
 #endif
index ae37ae26c0aedba618d3934f5898662f36d009a7..dd954fc55a10e5a4ce05703a9fa2ca4a14267b4d 100644 (file)
@@ -137,6 +137,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
     cc->handle_mmu_fault = mips_cpu_handle_mmu_fault;
 #else
     cc->do_unassigned_access = mips_cpu_unassigned_access;
+    cc->do_unaligned_access = mips_cpu_do_unaligned_access;
     cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
 #endif
 
index 6c2014eddde09502b0e2429df3b5cb927b4be97e..a9b2c7ae3873f7c063603a602aa13b6bb0f3351e 100644 (file)
@@ -3,6 +3,7 @@
 
 //#define DEBUG_OP
 
+#define ALIGNED_ONLY
 #define TARGET_HAS_ICE 1
 
 #define ELF_MACHINE    EM_MIPS
index 8af931abd9578f9eb8af81d21e58845c0c7374c1..4704216834c2174b39615dc6848b257e7440736f 100644 (file)
 #include <stdlib.h>
 #include "cpu.h"
 #include "qemu/host-utils.h"
-
 #include "exec/helper-proto.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
+#include "exec/cpu_ldst.h"
 
 #ifndef CONFIG_USER_ONLY
 static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global);
@@ -2128,28 +2124,12 @@ void helper_wait(CPUMIPSState *env)
 
 #if !defined(CONFIG_USER_ONLY)
 
-static void QEMU_NORETURN do_unaligned_access(CPUMIPSState *env,
-                                              target_ulong addr, int is_write,
-                                              int is_user, uintptr_t retaddr);
-
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
-static void do_unaligned_access(CPUMIPSState *env, target_ulong addr,
-                                int is_write, int is_user, uintptr_t retaddr)
+void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+                                  int is_write, int is_user, uintptr_t retaddr)
 {
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+
     env->CP0_BadVAddr = addr;
     do_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL, retaddr);
 }
index 13cf29b9d9130dabacc3c04fa188ab1648189d5a..76deb7b138c84d34e2f61fda8516dfcdaa62e297 100644 (file)
@@ -24,6 +24,7 @@
 #include "cpu.h"
 #include "disas/disas.h"
 #include "tcg-op.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index d1efdedf9dda71a8cdfb5a00383567bffdf3dfd3..6c98965b93201806d82d61ba088a44730339504d 100644 (file)
 #include "cpu.h"
 #include "mmu.h"
 #include "exec/exec-all.h"
-#include "exec/softmmu_exec.h"
+#include "exec/cpu_ldst.h"
 #include "qemu/host-utils.h"
 #include "exec/helper-proto.h"
 
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 /* Try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
index 7f0dfb66f258b24bd1e0b326c0f1026b137109b6..4541b9bff4ce13bfb61aa0d440951e25ba5890bf 100644 (file)
@@ -32,6 +32,7 @@
 #include "exec/exec-all.h"
 #include "disas/disas.h"
 #include "tcg-op.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index fb457c76af00d55290aeb97a113bc4d0b4cee930..ee1c6f61184f561637b2a6b9a053378f7d78a0a1 100644 (file)
  */
 
 #include "cpu.h"
+#include "exec/cpu_ldst.h"
 
 #ifndef CONFIG_USER_ONLY
-#include "exec/softmmu_exec.h"
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
 
 void tlb_fill(CPUState *cs, target_ulong addr, int is_write,
               int mmu_idx, uintptr_t retaddr)
index 40084f9a527b44809f2176f8b01224e4e56e4a20..b728718b641f451900cc9ac3640d78bb00779839 100644 (file)
@@ -26,6 +26,7 @@
 #include "qemu/log.h"
 #include "config.h"
 #include "qemu/bitops.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index a0c9fdc84b27b4d69965baaeeb0d78d208703f18..7dfc52d1598da26fb235cd70f6f975ffe1470002 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
 
 #include "helper_regs.h"
 
index d9c8c367120890c1fd55e16649035ee0653ffc86..02b627e47b08a6642f198c9df83a25d41ff54258 100644 (file)
 #include "exec/helper-proto.h"
 
 #include "helper_regs.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
+#include "exec/cpu_ldst.h"
 
 //#define DEBUG_OP
 
index a238bb2731eb3d4f54503337b0d5237c37864dd2..f029f41965a83d7b0aa3f08a74877cb5060c91de 100644 (file)
@@ -22,6 +22,7 @@
 #include "kvm_ppc.h"
 #include "mmu-hash64.h"
 #include "mmu-hash32.h"
+#include "exec/cpu_ldst.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
@@ -2903,22 +2904,6 @@ void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
 
 /*****************************************************************************/
 
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 /* try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
index 6283b2c36c6c2ceec6f65edd89490136a566bb8a..f08901470b11453160d749885d5a396a063d6625 100644 (file)
@@ -22,6 +22,7 @@
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "qemu/host-utils.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index d879ad63a16b9df31adce57e3aecb76c567398b5..b946ec1d5143c4e198b74f41c5e1644c7d2ffba1 100644 (file)
  */
 
 #include "cpu.h"
+#include "exec/cpu_ldst.h"
 #include "exec/helper-proto.h"
 
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif
-
 /* #define DEBUG_HELPER */
 #ifdef DEBUG_HELPER
 #define HELPER_LOG(x...) qemu_log(x)
index 3d756cae6ceba7bf87ea553bffb2cb5f8bba12c4..67ab1065aa45d4eac3b352931e61280cb44a08e8 100644 (file)
@@ -21,6 +21,7 @@
 #include "cpu.h"
 #include "exec/gdbstub.h"
 #include "qemu/timer.h"
+#include "exec/cpu_ldst.h"
 #ifndef CONFIG_USER_ONLY
 #include "sysemu/sysemu.h"
 #endif
index 5a29841d71c2061863692424a4c4a3856ce1a90a..5a55de86a13e469f4b64b6f8b77a216492f5f786 100644 (file)
 
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
 
 /*****************************************************************************/
 /* Softmmu support */
 #if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
 
 /* try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not
index 44c08f370d6aac58adf9f51eab628caddf1f0a57..9dae0256fac1d04b42ed63ccc0a3cd3114b365df 100644 (file)
@@ -28,9 +28,9 @@
 #ifdef CONFIG_KVM
 #include <linux/kvm.h>
 #endif
+#include "exec/cpu_ldst.h"
 
 #if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
 #include "sysemu/cpus.h"
 #include "sysemu/sysemu.h"
 #include "hw/s390x/ebcdic.h"
index cf65f01f60626403b841fb2288fe40674794f707..8ca4824d60992bcae766fef4f24480e52f4dab41 100644 (file)
@@ -33,6 +33,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "qemu/host-utils.h"
+#include "exec/cpu_ldst.h"
 
 /* global register indexes */
 static TCGv_ptr cpu_env;
index 39e1e7cbef4d2a1e48bc5c4c7265cdbcf2aa518f..74a5c4ea779532734b5f821c8377d05ba75e8bc7 100644 (file)
 #include <stdlib.h>
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
 
 #ifndef CONFIG_USER_ONLY
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
 
 void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
               uintptr_t retaddr)
index 169c87fc1b02ecb256e4a04b12c1d5ea437fedb5..8126818142099e9fa8e4e42173fd8d7fd83d2638 100644 (file)
@@ -23,6 +23,7 @@
 #include "cpu.h"
 #include "disas/disas.h"
 #include "tcg-op.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index 8e3e0de27707570484a0c045cc58978d46b4fde5..477c4d513693e9a3445e489888f2c00b3f6caac7 100644 (file)
@@ -81,5 +81,8 @@ void sparc_cpu_dump_state(CPUState *cpu, FILE *f,
 hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int sparc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cpu,
+                                                 vaddr addr, int is_write,
+                                                 int is_user, uintptr_t retaddr);
 
 #endif
index d9f37e9b6a19dde1a30abacd8ea35f97a7a36810..3a0ee504e50798cc88852cb59e9eb79bb10ebda5 100644 (file)
@@ -825,6 +825,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
     cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
 #else
     cc->do_unassigned_access = sparc_cpu_unassigned_access;
+    cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
     cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
 #endif
 
index f72451d53e676f2621142d439143030222505026..836f87f42f9883507e51c71927d4558deb1c68ac 100644 (file)
@@ -5,6 +5,8 @@
 #include "qemu-common.h"
 #include "qemu/bswap.h"
 
+#define ALIGNED_ONLY
+
 #if !defined(TARGET_SPARC64)
 #define TARGET_LONG_BITS 32
 #define TARGET_DPREGS 16
index b6b9866b93505741de367fadd17d1dc84cf93f44..03bd9f970652ea1de75979b381a38a238ea11071 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
-#if !defined(CONFIG_USER_ONLY)
-static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env,
-                                              target_ulong addr, int is_write,
-                                              int is_user, uintptr_t retaddr);
-#include "exec/softmmu_exec.h"
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-#endif
-
 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 /* Calculates TSB pointer value for fault page size 8k or 64k */
 static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
@@ -2425,11 +2405,13 @@ void sparc_cpu_unassigned_access(CPUState *cs, hwaddr addr,
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
-static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env,
-                                              target_ulong addr, int is_write,
-                                              int is_user, uintptr_t retaddr)
+void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs,
+                                                 vaddr addr, int is_write,
+                                                 int is_user, uintptr_t retaddr)
 {
-    SPARCCPU *cpu = sparc_env_get_cpu(env);
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
+
 #ifdef DEBUG_UNALIGNED
     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
            "\n", addr, env->pc);
index 652a181763e24586729f89987e6edd936eedf8a1..1ab07a18a2b5313d3c9a5b861024b306d2b0a49a 100644 (file)
@@ -28,6 +28,7 @@
 #include "disas/disas.h"
 #include "exec/helper-proto.h"
 #include "tcg-op.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-gen.h"
 
index 4f96ed350b397fd5cdbdb1d66fe1cd1b21d6ff0f..0266dbdf7b9caacb9f51da8eca8d0c328182ecf8 100644 (file)
@@ -10,6 +10,7 @@
  */
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
 
 #define SIGNBIT (uint32_t)0x80000000
 #define SIGNBIT64 ((uint64_t)1 << 63)
@@ -241,22 +242,6 @@ uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
 }
 
 #ifndef CONFIG_USER_ONLY
-#include "exec/softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
 void tlb_fill(CPUState *cs, target_ulong addr, int is_write,
               int mmu_idx, uintptr_t retaddr)
 {
index 3cccafe5ad9f0e97a9867290153dc69db6680a9d..5a8c7c89eebc840848e6d1cda18b9318787f2b1c 100644 (file)
@@ -18,6 +18,7 @@
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "qemu/log.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index c6cc2d91f46fd3d96eb890f13374e8bd6434ae5e..f320486a6892ff292f9d79889b75ed3aeca252c7 100644 (file)
@@ -89,5 +89,7 @@ void xtensa_cpu_dump_state(CPUState *cpu, FILE *f,
 hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
+                                    int is_write, int is_user, uintptr_t retaddr);
 
 #endif
index 6251f1c47e8e78a9d04f2a51a82c14c101803f6d..9d8801b70e5c24c2d17929d530a63714949b6740 100644 (file)
@@ -148,6 +148,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
     cc->gdb_read_register = xtensa_cpu_gdb_read_register;
     cc->gdb_write_register = xtensa_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
+    cc->do_unaligned_access = xtensa_cpu_do_unaligned_access;
     cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug;
 #endif
     dc->vmsd = &vmstate_xtensa_cpu;
index e210bacdffa59860d3b19507fdcff9a6b3bb7261..d797d2649a63c80e1e4bb699d35ba258be07b7f2 100644 (file)
@@ -28,6 +28,7 @@
 #ifndef CPU_XTENSA_H
 #define CPU_XTENSA_H
 
+#define ALIGNED_ONLY
 #define TARGET_LONG_BITS 32
 #define ELF_MACHINE EM_XTENSA
 
index 01edab4082b1bbb95053f9e5525c6800862479f0..dae13866efb16a9ef64fd2ea743bcf46bf2a1b4d 100644 (file)
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "qemu/host-utils.h"
-#include "exec/softmmu_exec.h"
+#include "exec/cpu_ldst.h"
 #include "exec/address-spaces.h"
+#include "qemu/timer.h"
 
-static void do_unaligned_access(CPUXtensaState *env,
-        target_ulong addr, int is_write, int is_user, uintptr_t retaddr);
-
-#define ALIGNED_ONLY
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
-static void do_unaligned_access(CPUXtensaState *env,
-        target_ulong addr, int is_write, int is_user, uintptr_t retaddr)
+void xtensa_cpu_do_unaligned_access(CPUState *cs,
+        vaddr addr, int is_write, int is_user, uintptr_t retaddr)
 {
-    XtensaCPU *cpu = xtensa_env_get_cpu(env);
+    XtensaCPU *cpu = XTENSA_CPU(cs);
+    CPUXtensaState *env = &cpu->env;
 
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
             !xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
index 57e56bd34dcb20b530448534dff859ffa9fe5d95..2f22cce845068e68b4659c12ffdca73f76c5a068 100644 (file)
@@ -36,6 +36,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "sysemu/sysemu.h"
+#include "exec/cpu_ldst.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
index a32aea66fa7ae14921871df4ffa1587e03b535b5..60c7493ac1129ff2d8fddccd2e38599188725534 100644 (file)
@@ -99,8 +99,6 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i64        1
 #define TCG_TARGET_HAS_mulsh_i64        1
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
 {
     __builtin___clear_cache((char *)start, (char *)stop);
index 73f10c4424b96d4a72ff971aa37d11ad9a315f81..1c719e286231cffb335f68c142749bcaf190ba6f 100644 (file)
@@ -86,8 +86,6 @@ extern bool use_idiv_instructions;
 #define TCG_TARGET_HAS_div_i32          use_idiv_instructions
 #define TCG_TARGET_HAS_rem_i32          0
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 extern bool tcg_target_deposit_valid(int ofs, int len);
 #define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
 
index d9102335f98b0b0aa77b13fb5dd4502670521339..4133dcf1a90382edeb37baa924a4f459c9c73962 100644 (file)
@@ -1407,7 +1407,8 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
         } else {
             retaddr = TCG_REG_RAX;
             tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
-            tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP, 0);
+            tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP,
+                       TCG_TARGET_CALL_STACK_OFFSET);
         }
     }
 
index 6c94e5cde0f07acaadea799327f18243ea529648..7a9980e70edb520c392e07550018cca2c4b0f360 100644 (file)
@@ -130,8 +130,6 @@ extern bool have_bmi1;
 #define TCG_TARGET_HAS_mulsh_i64        0
 #endif
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 #define TCG_TARGET_deposit_i32_valid(ofs, len) \
     (((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || \
      ((ofs) == 0 && (len) == 16))
index 3a59b503490aa034512dab88837a8560ce8f8943..d67558988adbe7ad1be03b20d64ded4d8e97aa05 100644 (file)
@@ -160,8 +160,6 @@ typedef enum {
 #define TCG_TARGET_HAS_mulsh_i64        0
 #define TCG_TARGET_HAS_trunc_shr_i32    0
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 #define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16)
 #define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16)
 
index b5face8b4de9ee7dc6ed6985a4e7f2e66a09b35f..c88a1c927247ba9141d8289e86047deeeead3983 100644 (file)
@@ -118,8 +118,6 @@ extern bool use_mips32r2_instructions;
 #define TCG_TARGET_HAS_ext16s_i32       use_mips32r2_instructions
 #define TCG_TARGET_HAS_rot_i32          use_mips32r2_instructions
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 /* optional instructions automatically implemented */
 #define TCG_TARGET_HAS_neg_i32          0 /* sub  rd, zero, rt   */
 #define TCG_TARGET_HAS_ext8u_i32        0 /* andi rt, rs, 0xff   */
index 77da2f942af5c01cb94769ca59654f32eb7403ce..16cebbe16d8da1078c91a5fa28d88eb545597bca 100644 (file)
@@ -889,17 +889,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             break;
 
         CASE_OP_32_64(ld8u):
-        case INDEX_op_qemu_ld8u:
             mask = 0xff;
             break;
         CASE_OP_32_64(ld16u):
-        case INDEX_op_qemu_ld16u:
             mask = 0xffff;
             break;
         case INDEX_op_ld32u_i64:
-#if TCG_TARGET_REG_BITS == 64
-        case INDEX_op_qemu_ld32u:
-#endif
             mask = 0xffffffffu;
             break;
 
index dd7e55794833ac3eda22cbd5d65189d83500519c..05069ae2d80cd579353854bf39ebd8be9bc28945 100644 (file)
@@ -100,8 +100,6 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i32        0
 #define TCG_TARGET_HAS_mulsh_i32        0
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 #define TCG_AREG0 TCG_REG_R27
 
 #define tcg_qemu_tb_exec(env, tb_ptr) \
index 29f479a3cf2e8681696bb723a52f907008be024a..f2360c869a74c36f65fbd466af9202ebbf94d7cf 100644 (file)
@@ -124,8 +124,6 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i64        1
 #define TCG_TARGET_HAS_mulsh_i64        1
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 #define TCG_AREG0 TCG_REG_R27
 
 #define TCG_TARGET_EXTEND_ARGS 1
index ad2c6ddaf4af57ef0c86895c17a26ea572ebeb48..5acc28ca6b161bda376e5740864e4cdb83433054 100644 (file)
@@ -100,8 +100,6 @@ typedef enum TCGReg {
 #define TCG_TARGET_HAS_muluh_i64        0
 #define TCG_TARGET_HAS_mulsh_i64        0
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 extern bool tcg_target_deposit_valid(int ofs, int len);
 #define TCG_TARGET_deposit_i32_valid  tcg_target_deposit_valid
 #define TCG_TARGET_deposit_i64_valid  tcg_target_deposit_valid
index 473bfc71fdde7b08c190de56ae29bb462f501f39..089f9761ca353151696aec6569016999d6e557de 100644 (file)
@@ -140,8 +140,6 @@ typedef enum {
 #define TCG_TARGET_HAS_muluh_i64        0
 #define TCG_TARGET_HAS_mulsh_i64        0
 
-#define TCG_TARGET_HAS_new_ldst         1
-
 #define TCG_AREG0 TCG_REG_I0
 
 static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
index 719533ac39a1c00d317da2982b5743052ac73f00..019dd9b6fb0b4a545531ef3377febf705a6e40f8 100644 (file)
@@ -2718,7 +2718,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
 #define tcg_gen_bswap16_tl tcg_gen_bswap16_i32
 #define tcg_gen_bswap32_tl tcg_gen_bswap32_i32
 #define tcg_gen_concat_tl_i64 tcg_gen_concat_i32_i64
-#define tcg_gen_extr_tl_i64 tcg_gen_extr_i32_i64
+#define tcg_gen_extr_i64_tl tcg_gen_extr_i64_i32
 #define tcg_gen_andc_tl tcg_gen_andc_i32
 #define tcg_gen_eqv_tl tcg_gen_eqv_i32
 #define tcg_gen_nand_tl tcg_gen_nand_i32
index 71ba64ac169b47bd43dab0c54800c003f9f115ff..042d442c7e9fca910120b2c7a117d87d10f01314 100644 (file)
@@ -185,106 +185,20 @@ DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
 DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
 DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)
 
-#define IMPL_NEW_LDST \
-    (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS \
-     | IMPL(TCG_TARGET_HAS_new_ldst))
-
-#if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
-DEF(qemu_ld_i32, 1, 1, 2, IMPL_NEW_LDST)
-DEF(qemu_st_i32, 0, 2, 2, IMPL_NEW_LDST)
-# if TCG_TARGET_REG_BITS == 64
-DEF(qemu_ld_i64, 1, 1, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
-DEF(qemu_st_i64, 0, 2, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
-# else
-DEF(qemu_ld_i64, 2, 1, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
-DEF(qemu_st_i64, 0, 3, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
-# endif
-#else
-DEF(qemu_ld_i32, 1, 2, 2, IMPL_NEW_LDST)
-DEF(qemu_st_i32, 0, 3, 2, IMPL_NEW_LDST)
-DEF(qemu_ld_i64, 2, 2, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
-DEF(qemu_st_i64, 0, 4, 2, IMPL_NEW_LDST | TCG_OPF_64BIT)
-#endif
-
-#undef IMPL_NEW_LDST
-
-#define IMPL_OLD_LDST \
-    (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS \
-     | IMPL(!TCG_TARGET_HAS_new_ldst))
-
-#if TCG_TARGET_REG_BITS == 32
-#if TARGET_LONG_BITS == 32
-DEF(qemu_ld8u, 1, 1, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_ld8u, 1, 2, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_ld8s, 1, 1, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_ld8s, 1, 2, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_ld16u, 1, 1, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_ld16u, 1, 2, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_ld16s, 1, 1, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_ld16s, 1, 2, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_ld32, 1, 1, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_ld32, 1, 2, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_ld64, 2, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-#else
-DEF(qemu_ld64, 2, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-#endif
-
-#if TARGET_LONG_BITS == 32
-DEF(qemu_st8, 0, 2, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_st8, 0, 3, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_st16, 0, 2, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_st16, 0, 3, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_st32, 0, 2, 1, IMPL_OLD_LDST)
-#else
-DEF(qemu_st32, 0, 3, 1, IMPL_OLD_LDST)
-#endif
-#if TARGET_LONG_BITS == 32
-DEF(qemu_st64, 0, 3, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-#else
-DEF(qemu_st64, 0, 4, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-#endif
-
-#else /* TCG_TARGET_REG_BITS == 32 */
-
-DEF(qemu_ld8u, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_ld8s, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_ld16u, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_ld16s, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_ld32, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_ld32u, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_ld32s, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_ld64, 1, 1, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-
-DEF(qemu_st8, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_st16, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_st32, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-DEF(qemu_st64, 0, 2, 1, IMPL_OLD_LDST | TCG_OPF_64BIT)
-
-#endif /* TCG_TARGET_REG_BITS != 32 */
-
-#undef IMPL_OLD_LDST
-
+#define TLADDR_ARGS    (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? 1 : 2)
+#define DATA64_ARGS  (TCG_TARGET_REG_BITS == 64 ? 1 : 2)
+
+DEF(qemu_ld_i32, 1, TLADDR_ARGS, 2,
+    TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st_i32, 0, TLADDR_ARGS + 1, 2,
+    TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld_i64, DATA64_ARGS, TLADDR_ARGS, 2,
+    TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT)
+DEF(qemu_st_i64, 0, TLADDR_ARGS + DATA64_ARGS, 2,
+    TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT)
+
+#undef TLADDR_ARGS
+#undef DATA64_ARGS
 #undef IMPL
 #undef IMPL64
 #undef DEF
index 2c5732da173fd5a35e98861ee7b7395de9e3819e..dae4b7cb007e366f786ba5479919648639b2d2cb 100644 (file)
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -941,97 +941,26 @@ static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
     return op;
 }
 
-static const TCGOpcode old_ld_opc[8] = {
-    [MO_UB] = INDEX_op_qemu_ld8u,
-    [MO_SB] = INDEX_op_qemu_ld8s,
-    [MO_UW] = INDEX_op_qemu_ld16u,
-    [MO_SW] = INDEX_op_qemu_ld16s,
-#if TCG_TARGET_REG_BITS == 32
-    [MO_UL] = INDEX_op_qemu_ld32,
-    [MO_SL] = INDEX_op_qemu_ld32,
-#else
-    [MO_UL] = INDEX_op_qemu_ld32u,
-    [MO_SL] = INDEX_op_qemu_ld32s,
-#endif
-    [MO_Q]  = INDEX_op_qemu_ld64,
-};
-
-static const TCGOpcode old_st_opc[4] = {
-    [MO_UB] = INDEX_op_qemu_st8,
-    [MO_UW] = INDEX_op_qemu_st16,
-    [MO_UL] = INDEX_op_qemu_st32,
-    [MO_Q]  = INDEX_op_qemu_st64,
-};
-
 void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
 {
     memop = tcg_canonicalize_memop(memop, 0, 0);
 
-    if (TCG_TARGET_HAS_new_ldst) {
-        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i32;
-        tcg_add_param_i32(val);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = memop;
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-        return;
-    }
-
-    /* The old opcodes only support target-endian memory operations.  */
-    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
-    assert(old_ld_opc[memop & MO_SSIZE] != 0);
-
-    if (TCG_TARGET_REG_BITS == 32) {
-        *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
-        tcg_add_param_i32(val);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-    } else {
-        TCGv_i64 val64 = tcg_temp_new_i64();
-
-        *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
-        tcg_add_param_i64(val64);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-
-        tcg_gen_trunc_i64_i32(val, val64);
-        tcg_temp_free_i64(val64);
-    }
+    *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i32;
+    tcg_add_param_i32(val);
+    tcg_add_param_tl(addr);
+    *tcg_ctx.gen_opparam_ptr++ = memop;
+    *tcg_ctx.gen_opparam_ptr++ = idx;
 }
 
 void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
 {
     memop = tcg_canonicalize_memop(memop, 0, 1);
 
-    if (TCG_TARGET_HAS_new_ldst) {
-        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i32;
-        tcg_add_param_i32(val);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = memop;
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-        return;
-    }
-
-    /* The old opcodes only support target-endian memory operations.  */
-    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
-    assert(old_st_opc[memop & MO_SIZE] != 0);
-
-    if (TCG_TARGET_REG_BITS == 32) {
-        *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
-        tcg_add_param_i32(val);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-    } else {
-        TCGv_i64 val64 = tcg_temp_new_i64();
-
-        tcg_gen_extu_i32_i64(val64, val);
-
-        *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
-        tcg_add_param_i64(val64);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-
-        tcg_temp_free_i64(val64);
-    }
+    *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i32;
+    tcg_add_param_i32(val);
+    tcg_add_param_tl(addr);
+    *tcg_ctx.gen_opparam_ptr++ = memop;
+    *tcg_ctx.gen_opparam_ptr++ = idx;
 }
 
 void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
@@ -1050,22 +979,10 @@ void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
     }
 #endif
 
-    if (TCG_TARGET_HAS_new_ldst) {
-        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i64;
-        tcg_add_param_i64(val);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = memop;
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-        return;
-    }
-
-    /* The old opcodes only support target-endian memory operations.  */
-    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
-    assert(old_ld_opc[memop & MO_SSIZE] != 0);
-
-    *tcg_ctx.gen_opc_ptr++ = old_ld_opc[memop & MO_SSIZE];
+    *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i64;
     tcg_add_param_i64(val);
     tcg_add_param_tl(addr);
+    *tcg_ctx.gen_opparam_ptr++ = memop;
     *tcg_ctx.gen_opparam_ptr++ = idx;
 }
 
@@ -1080,22 +997,10 @@ void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
     }
 #endif
 
-    if (TCG_TARGET_HAS_new_ldst) {
-        *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i64;
-        tcg_add_param_i64(val);
-        tcg_add_param_tl(addr);
-        *tcg_ctx.gen_opparam_ptr++ = memop;
-        *tcg_ctx.gen_opparam_ptr++ = idx;
-        return;
-    }
-
-    /* The old opcodes only support target-endian memory operations.  */
-    assert((memop & MO_BSWAP) == MO_TE || (memop & MO_SIZE) == MO_8);
-    assert(old_st_opc[memop & MO_SIZE] != 0);
-
-    *tcg_ctx.gen_opc_ptr++ = old_st_opc[memop & MO_SIZE];
+    *tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i64;
     tcg_add_param_i64(val);
     tcg_add_param_tl(addr);
+    *tcg_ctx.gen_opparam_ptr++ = memop;
     *tcg_ctx.gen_opparam_ptr++ = idx;
 }
 
index 2efa3331660c2ae6f6bfede1e95c11c2f3a0a2d7..997a70433b6d2298c5410ec582751371b8d62db3 100644 (file)
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -909,19 +909,6 @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
 # define helper_ret_stq_mmu   helper_le_stq_mmu
 #endif
 
-uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-
-void helper_stb_mmu(CPUArchState *env, target_ulong addr,
-                    uint8_t val, int mmu_idx);
-void helper_stw_mmu(CPUArchState *env, target_ulong addr,
-                    uint16_t val, int mmu_idx);
-void helper_stl_mmu(CPUArchState *env, target_ulong addr,
-                    uint32_t val, int mmu_idx);
-void helper_stq_mmu(CPUArchState *env, target_ulong addr,
-                    uint64_t val, int mmu_idx);
 #endif /* CONFIG_SOFTMMU */
 
 #endif /* TCG_H */
index 375e590d2bfde05096acbadfa634e49883c5378c..03a7b46958eed6aa850474c015cacc387c1489bb 100644 (file)
@@ -227,21 +227,11 @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
 #endif
 #endif /* TCG_TARGET_REG_BITS == 64 */
 
-    { INDEX_op_qemu_ld8u, { R, L } },
-    { INDEX_op_qemu_ld8s, { R, L } },
-    { INDEX_op_qemu_ld16u, { R, L } },
-    { INDEX_op_qemu_ld16s, { R, L } },
-    { INDEX_op_qemu_ld32, { R, L } },
-#if TCG_TARGET_REG_BITS == 64
-    { INDEX_op_qemu_ld32u, { R, L } },
-    { INDEX_op_qemu_ld32s, { R, L } },
-#endif
-    { INDEX_op_qemu_ld64, { R64, L } },
+    { INDEX_op_qemu_ld_i32, { R, L } },
+    { INDEX_op_qemu_ld_i64, { R64, L } },
 
-    { INDEX_op_qemu_st8, { R, S } },
-    { INDEX_op_qemu_st16, { R, S } },
-    { INDEX_op_qemu_st32, { R, S } },
-    { INDEX_op_qemu_st64, { R64, S } },
+    { INDEX_op_qemu_st_i32, { R, S } },
+    { INDEX_op_qemu_st_i64, { R64, S } },
 
 #if TCG_TARGET_HAS_ext8s_i32
     { INDEX_op_ext8s_i32, { R, R } },
@@ -767,58 +757,52 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         tcg_out8(s, args[2]);           /* condition */
         tci_out_label(s, args[3]);
         break;
-    case INDEX_op_qemu_ld8u:
-    case INDEX_op_qemu_ld8s:
-    case INDEX_op_qemu_ld16u:
-    case INDEX_op_qemu_ld16s:
-    case INDEX_op_qemu_ld32:
-#if TCG_TARGET_REG_BITS == 64
-    case INDEX_op_qemu_ld32s:
-    case INDEX_op_qemu_ld32u:
-#endif
+    case INDEX_op_qemu_ld_i32:
         tcg_out_r(s, *args++);
         tcg_out_r(s, *args++);
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-        tcg_out_r(s, *args++);
-#endif
+        if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+            tcg_out_r(s, *args++);
+        }
+        tcg_out_i(s, *args++);
 #ifdef CONFIG_SOFTMMU
         tcg_out_i(s, *args);
 #endif
         break;
-    case INDEX_op_qemu_ld64:
-        tcg_out_r(s, *args++);
-#if TCG_TARGET_REG_BITS == 32
+    case INDEX_op_qemu_ld_i64:
         tcg_out_r(s, *args++);
-#endif
-        tcg_out_r(s, *args++);
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+        if (TCG_TARGET_REG_BITS == 32) {
+            tcg_out_r(s, *args++);
+        }
         tcg_out_r(s, *args++);
-#endif
+        if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+            tcg_out_r(s, *args++);
+        }
+        tcg_out_i(s, *args++);
 #ifdef CONFIG_SOFTMMU
         tcg_out_i(s, *args);
 #endif
         break;
-    case INDEX_op_qemu_st8:
-    case INDEX_op_qemu_st16:
-    case INDEX_op_qemu_st32:
+    case INDEX_op_qemu_st_i32:
         tcg_out_r(s, *args++);
         tcg_out_r(s, *args++);
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-        tcg_out_r(s, *args++);
-#endif
+        if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+            tcg_out_r(s, *args++);
+        }
+        tcg_out_i(s, *args++);
 #ifdef CONFIG_SOFTMMU
         tcg_out_i(s, *args);
 #endif
         break;
-    case INDEX_op_qemu_st64:
-        tcg_out_r(s, *args++);
-#if TCG_TARGET_REG_BITS == 32
-        tcg_out_r(s, *args++);
-#endif
+    case INDEX_op_qemu_st_i64:
         tcg_out_r(s, *args++);
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+        if (TCG_TARGET_REG_BITS == 32) {
+            tcg_out_r(s, *args++);
+        }
         tcg_out_r(s, *args++);
-#endif
+        if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
+            tcg_out_r(s, *args++);
+        }
+        tcg_out_i(s, *args++);
 #ifdef CONFIG_SOFTMMU
         tcg_out_i(s, *args);
 #endif
index 0be5acdb81172c03755a3f3adc584656f3a8ab6a..bd1e97468c915aa1d7fd47f1ee370d5402d43f91 100644 (file)
 #define TCG_TARGET_HAS_mulu2_i32        1
 #endif /* TCG_TARGET_REG_BITS == 64 */
 
-#define TCG_TARGET_HAS_new_ldst         0
-
 /* Number of registers available.
    For 32 bit hosts, we need more than 8 registers (call arguments). */
 /* #define TCG_TARGET_NB_REGS 8 */
diff --git a/tci.c b/tci.c
index 6523ab82f4de5d33c8d1adbb73139f5fa85ffe57..4711ee4817fb39bd4780d2d333270a02892b163c 100644 (file)
--- a/tci.c
+++ b/tci.c
@@ -26,6 +26,7 @@
 
 #include "qemu-common.h"
 #include "exec/exec-all.h"           /* MAX_OPC_PARAM_IARGS */
+#include "exec/cpu_ldst.h"
 #include "tcg-op.h"
 
 /* Marker for missing code. */
@@ -116,16 +117,6 @@ static void tci_write_reg(TCGReg index, tcg_target_ulong value)
     tci_reg[index] = value;
 }
 
-static void tci_write_reg8s(TCGReg index, int8_t value)
-{
-    tci_write_reg(index, value);
-}
-
-static void tci_write_reg16s(TCGReg index, int16_t value)
-{
-    tci_write_reg(index, value);
-}
-
 #if TCG_TARGET_REG_BITS == 64
 static void tci_write_reg32s(TCGReg index, int32_t value)
 {
@@ -138,11 +129,6 @@ static void tci_write_reg8(TCGReg index, uint8_t value)
     tci_write_reg(index, value);
 }
 
-static void tci_write_reg16(TCGReg index, uint16_t value)
-{
-    tci_write_reg(index, value);
-}
-
 static void tci_write_reg32(TCGReg index, uint32_t value)
 {
     tci_write_reg(index, value);
@@ -433,6 +419,53 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
     return result;
 }
 
+#ifdef CONFIG_SOFTMMU
+# define mmuidx          tci_read_i(&tb_ptr)
+# define qemu_ld_ub \
+    helper_ret_ldub_mmu(env, taddr, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_ld_leuw \
+    helper_le_lduw_mmu(env, taddr, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_ld_leul \
+    helper_le_ldul_mmu(env, taddr, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_ld_leq \
+    helper_le_ldq_mmu(env, taddr, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_ld_beuw \
+    helper_be_lduw_mmu(env, taddr, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_ld_beul \
+    helper_be_ldul_mmu(env, taddr, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_ld_beq \
+    helper_be_ldq_mmu(env, taddr, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_st_b(X) \
+    helper_ret_stb_mmu(env, taddr, X, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_st_lew(X) \
+    helper_le_stw_mmu(env, taddr, X, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_st_lel(X) \
+    helper_le_stl_mmu(env, taddr, X, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_st_leq(X) \
+    helper_le_stq_mmu(env, taddr, X, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_st_bew(X) \
+    helper_be_stw_mmu(env, taddr, X, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_st_bel(X) \
+    helper_be_stl_mmu(env, taddr, X, mmuidx, (uintptr_t)tb_ptr)
+# define qemu_st_beq(X) \
+    helper_be_stq_mmu(env, taddr, X, mmuidx, (uintptr_t)tb_ptr)
+#else
+# define qemu_ld_ub      ldub_p(g2h(taddr))
+# define qemu_ld_leuw    lduw_le_p(g2h(taddr))
+# define qemu_ld_leul    (uint32_t)ldl_le_p(g2h(taddr))
+# define qemu_ld_leq     ldq_le_p(g2h(taddr))
+# define qemu_ld_beuw    lduw_be_p(g2h(taddr))
+# define qemu_ld_beul    (uint32_t)ldl_be_p(g2h(taddr))
+# define qemu_ld_beq     ldq_be_p(g2h(taddr))
+# define qemu_st_b(X)    stb_p(g2h(taddr), X)
+# define qemu_st_lew(X)  stw_le_p(g2h(taddr), X)
+# define qemu_st_lel(X)  stl_le_p(g2h(taddr), X)
+# define qemu_st_leq(X)  stq_le_p(g2h(taddr), X)
+# define qemu_st_bew(X)  stw_be_p(g2h(taddr), X)
+# define qemu_st_bel(X)  stl_be_p(g2h(taddr), X)
+# define qemu_st_beq(X)  stq_be_p(g2h(taddr), X)
+#endif
+
 /* Interpret pseudo code in tb. */
 uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
 {
@@ -456,9 +489,6 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
         tcg_target_ulong label;
         TCGCond condition;
         target_ulong taddr;
-#ifndef CONFIG_SOFTMMU
-        tcg_target_ulong host_addr;
-#endif
         uint8_t tmp8;
         uint16_t tmp16;
         uint32_t tmp32;
@@ -466,6 +496,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
 #if TCG_TARGET_REG_BITS == 32
         uint64_t v64;
 #endif
+        TCGMemOp memop;
 
 #if defined(GETPC)
         tci_tb_ptr = (uintptr_t)tb_ptr;
@@ -1086,145 +1117,145 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
             assert(tb_ptr == old_code_ptr + op_size);
             tb_ptr += (int32_t)t0;
             continue;
-        case INDEX_op_qemu_ld8u:
-            t0 = *tb_ptr++;
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp8 = *(uint8_t *)(host_addr + GUEST_BASE);
-#endif
-            tci_write_reg8(t0, tmp8);
-            break;
-        case INDEX_op_qemu_ld8s:
+        case INDEX_op_qemu_ld_i32:
             t0 = *tb_ptr++;
             taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp8 = *(uint8_t *)(host_addr + GUEST_BASE);
-#endif
-            tci_write_reg8s(t0, tmp8);
-            break;
-        case INDEX_op_qemu_ld16u:
-            t0 = *tb_ptr++;
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE));
-#endif
-            tci_write_reg16(t0, tmp16);
-            break;
-        case INDEX_op_qemu_ld16s:
-            t0 = *tb_ptr++;
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE));
-#endif
-            tci_write_reg16s(t0, tmp16);
-            break;
-#if TCG_TARGET_REG_BITS == 64
-        case INDEX_op_qemu_ld32u:
-            t0 = *tb_ptr++;
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
-#endif
-            tci_write_reg32(t0, tmp32);
-            break;
-        case INDEX_op_qemu_ld32s:
-            t0 = *tb_ptr++;
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
-#endif
-            tci_write_reg32s(t0, tmp32);
-            break;
-#endif /* TCG_TARGET_REG_BITS == 64 */
-        case INDEX_op_qemu_ld32:
-            t0 = *tb_ptr++;
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE));
-#endif
-            tci_write_reg32(t0, tmp32);
+            memop = tci_read_i(&tb_ptr);
+            switch (memop) {
+            case MO_UB:
+                tmp32 = qemu_ld_ub;
+                break;
+            case MO_SB:
+                tmp32 = (int8_t)qemu_ld_ub;
+                break;
+            case MO_LEUW:
+                tmp32 = qemu_ld_leuw;
+                break;
+            case MO_LESW:
+                tmp32 = (int16_t)qemu_ld_leuw;
+                break;
+            case MO_LEUL:
+                tmp32 = qemu_ld_leul;
+                break;
+            case MO_BEUW:
+                tmp32 = qemu_ld_beuw;
+                break;
+            case MO_BESW:
+                tmp32 = (int16_t)qemu_ld_beuw;
+                break;
+            case MO_BEUL:
+                tmp32 = qemu_ld_beul;
+                break;
+            default:
+                tcg_abort();
+            }
+            tci_write_reg(t0, tmp32);
             break;
-        case INDEX_op_qemu_ld64:
+        case INDEX_op_qemu_ld_i64:
             t0 = *tb_ptr++;
-#if TCG_TARGET_REG_BITS == 32
-            t1 = *tb_ptr++;
-#endif
+            if (TCG_TARGET_REG_BITS == 32) {
+                t1 = *tb_ptr++;
+            }
             taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            tmp64 = helper_ldq_mmu(env, taddr, tci_read_i(&tb_ptr));
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            tmp64 = tswap64(*(uint64_t *)(host_addr + GUEST_BASE));
-#endif
+            memop = tci_read_i(&tb_ptr);
+            switch (memop) {
+            case MO_UB:
+                tmp64 = qemu_ld_ub;
+                break;
+            case MO_SB:
+                tmp64 = (int8_t)qemu_ld_ub;
+                break;
+            case MO_LEUW:
+                tmp64 = qemu_ld_leuw;
+                break;
+            case MO_LESW:
+                tmp64 = (int16_t)qemu_ld_leuw;
+                break;
+            case MO_LEUL:
+                tmp64 = qemu_ld_leul;
+                break;
+            case MO_LESL:
+                tmp64 = (int32_t)qemu_ld_leul;
+                break;
+            case MO_LEQ:
+                tmp64 = qemu_ld_leq;
+                break;
+            case MO_BEUW:
+                tmp64 = qemu_ld_beuw;
+                break;
+            case MO_BESW:
+                tmp64 = (int16_t)qemu_ld_beuw;
+                break;
+            case MO_BEUL:
+                tmp64 = qemu_ld_beul;
+                break;
+            case MO_BESL:
+                tmp64 = (int32_t)qemu_ld_beul;
+                break;
+            case MO_BEQ:
+                tmp64 = qemu_ld_beq;
+                break;
+            default:
+                tcg_abort();
+            }
             tci_write_reg(t0, tmp64);
-#if TCG_TARGET_REG_BITS == 32
-            tci_write_reg(t1, tmp64 >> 32);
-#endif
-            break;
-        case INDEX_op_qemu_st8:
-            t0 = tci_read_r8(&tb_ptr);
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            t2 = tci_read_i(&tb_ptr);
-            helper_stb_mmu(env, taddr, t0, t2);
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            *(uint8_t *)(host_addr + GUEST_BASE) = t0;
-#endif
-            break;
-        case INDEX_op_qemu_st16:
-            t0 = tci_read_r16(&tb_ptr);
-            taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            t2 = tci_read_i(&tb_ptr);
-            helper_stw_mmu(env, taddr, t0, t2);
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            *(uint16_t *)(host_addr + GUEST_BASE) = tswap16(t0);
-#endif
+            if (TCG_TARGET_REG_BITS == 32) {
+                tci_write_reg(t1, tmp64 >> 32);
+            }
             break;
-        case INDEX_op_qemu_st32:
-            t0 = tci_read_r32(&tb_ptr);
+        case INDEX_op_qemu_st_i32:
+            t0 = tci_read_r(&tb_ptr);
             taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            t2 = tci_read_i(&tb_ptr);
-            helper_stl_mmu(env, taddr, t0, t2);
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            *(uint32_t *)(host_addr + GUEST_BASE) = tswap32(t0);
-#endif
+            memop = tci_read_i(&tb_ptr);
+            switch (memop) {
+            case MO_UB:
+                qemu_st_b(t0);
+                break;
+            case MO_LEUW:
+                qemu_st_lew(t0);
+                break;
+            case MO_LEUL:
+                qemu_st_lel(t0);
+                break;
+            case MO_BEUW:
+                qemu_st_bew(t0);
+                break;
+            case MO_BEUL:
+                qemu_st_bel(t0);
+                break;
+            default:
+                tcg_abort();
+            }
             break;
-        case INDEX_op_qemu_st64:
+        case INDEX_op_qemu_st_i64:
             tmp64 = tci_read_r64(&tb_ptr);
             taddr = tci_read_ulong(&tb_ptr);
-#ifdef CONFIG_SOFTMMU
-            t2 = tci_read_i(&tb_ptr);
-            helper_stq_mmu(env, taddr, tmp64, t2);
-#else
-            host_addr = (tcg_target_ulong)taddr;
-            *(uint64_t *)(host_addr + GUEST_BASE) = tswap64(tmp64);
-#endif
+            memop = tci_read_i(&tb_ptr);
+            switch (memop) {
+            case MO_UB:
+                qemu_st_b(tmp64);
+                break;
+            case MO_LEUW:
+                qemu_st_lew(tmp64);
+                break;
+            case MO_LEUL:
+                qemu_st_lel(tmp64);
+                break;
+            case MO_LEQ:
+                qemu_st_leq(tmp64);
+                break;
+            case MO_BEUW:
+                qemu_st_bew(tmp64);
+                break;
+            case MO_BEUL:
+                qemu_st_bel(tmp64);
+                break;
+            case MO_BEQ:
+                qemu_st_beq(tmp64);
+                break;
+            default:
+                tcg_abort();
+            }
             break;
         default:
             TODO();
index 6b294a7dbc8407380c6b02a88e0255ff2ca570f3..361bb7b6e347eea81a53baeaad7ad338daaf6f70 100644 (file)
@@ -133,7 +133,7 @@ check-qtest-i386-y += tests/ide-test$(EXESUF)
 check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
 gcov-files-i386-y += hw/block/hd-geometry.c
 check-qtest-i386-y += tests/boot-order-test$(EXESUF)
-check-qtest-i386-y += tests/acpi-test$(EXESUF)
+check-qtest-i386-y += tests/bios-tables-test$(EXESUF)
 check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-i386-y += tests/i440fx-test$(EXESUF)
 check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
@@ -290,7 +290,7 @@ tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
-tests/acpi-test$(EXESUF): tests/acpi-test.o $(libqos-obj-y)
+tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
diff --git a/tests/acpi-test.c b/tests/acpi-test.c
deleted file mode 100644 (file)
index 76fbccf..0000000
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * Boot order test cases.
- *
- * Copyright (c) 2013 Red Hat Inc.
- *
- * Authors:
- *  Michael S. Tsirkin <mst@redhat.com>,
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include "qemu-common.h"
-#include "libqtest.h"
-#include "qemu/compiler.h"
-#include "hw/i386/acpi-defs.h"
-
-#define MACHINE_PC "pc"
-#define MACHINE_Q35 "q35"
-
-#define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
-
-/* DSDT and SSDTs format */
-typedef struct {
-    AcpiTableHeader header;
-    gchar *aml;            /* aml bytecode from guest */
-    gsize aml_len;
-    gchar *aml_file;
-    gchar *asl;            /* asl code generated from aml */
-    gsize asl_len;
-    gchar *asl_file;
-    bool tmp_files_retain;   /* do not delete the temp asl/aml */
-} QEMU_PACKED AcpiSdtTable;
-
-typedef struct {
-    const char *machine;
-    uint32_t rsdp_addr;
-    AcpiRsdpDescriptor rsdp_table;
-    AcpiRsdtDescriptorRev1 rsdt_table;
-    AcpiFadtDescriptorRev1 fadt_table;
-    AcpiFacsDescriptorRev1 facs_table;
-    uint32_t *rsdt_tables_addr;
-    int rsdt_tables_nr;
-    GArray *tables;
-} test_data;
-
-#define LOW(x) ((x) & 0xff)
-#define HIGH(x) ((x) >> 8)
-
-#define SIGNATURE 0xdead
-#define SIGNATURE_OFFSET 0x10
-#define BOOT_SECTOR_ADDRESS 0x7c00
-
-#define ACPI_READ_FIELD(field, addr)           \
-    do {                                       \
-        switch (sizeof(field)) {               \
-        case 1:                                \
-            field = readb(addr);               \
-            break;                             \
-        case 2:                                \
-            field = readw(addr);               \
-            break;                             \
-        case 4:                                \
-            field = readl(addr);               \
-            break;                             \
-        case 8:                                \
-            field = readq(addr);               \
-            break;                             \
-        default:                               \
-            g_assert(false);                   \
-        }                                      \
-        addr += sizeof(field);                  \
-    } while (0);
-
-#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
-    do {                                        \
-        int idx;                                \
-        for (idx = 0; idx < length; ++idx) {    \
-            ACPI_READ_FIELD(arr[idx], addr);    \
-        }                                       \
-    } while (0);
-
-#define ACPI_READ_ARRAY(arr, addr)                               \
-    ACPI_READ_ARRAY_PTR(arr, sizeof(arr)/sizeof(arr[0]), addr)
-
-#define ACPI_READ_TABLE_HEADER(table, addr)                      \
-    do {                                                         \
-        ACPI_READ_FIELD((table)->signature, addr);               \
-        ACPI_READ_FIELD((table)->length, addr);                  \
-        ACPI_READ_FIELD((table)->revision, addr);                \
-        ACPI_READ_FIELD((table)->checksum, addr);                \
-        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
-        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
-        ACPI_READ_FIELD((table)->oem_revision, addr);            \
-        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
-        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
-    } while (0);
-
-#define ACPI_ASSERT_CMP(actual, expected) do { \
-    uint32_t ACPI_ASSERT_CMP_le = cpu_to_le32(actual); \
-    char ACPI_ASSERT_CMP_str[5] = {}; \
-    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 4); \
-    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
-} while (0)
-
-#define ACPI_ASSERT_CMP64(actual, expected) do { \
-    uint64_t ACPI_ASSERT_CMP_le = cpu_to_le64(actual); \
-    char ACPI_ASSERT_CMP_str[9] = {}; \
-    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 8); \
-    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
-} while (0)
-
-/* Boot sector code: write SIGNATURE into memory,
- * then halt.
- * Q35 machine requires a minimum 0x7e000 bytes disk.
- * (bug or feature?)
- */
-static uint8_t boot_sector[0x7e000] = {
-    /* 7c00: mov $0xdead,%ax */
-    [0x00] = 0xb8,
-    [0x01] = LOW(SIGNATURE),
-    [0x02] = HIGH(SIGNATURE),
-    /* 7c03:  mov %ax,0x7c10 */
-    [0x03] = 0xa3,
-    [0x04] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
-    [0x05] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
-    /* 7c06: cli */
-    [0x06] = 0xfa,
-    /* 7c07: hlt */
-    [0x07] = 0xf4,
-    /* 7c08: jmp 0x7c07=0x7c0a-3 */
-    [0x08] = 0xeb,
-    [0x09] = LOW(-3),
-    /* We mov 0xdead here: set value to make debugging easier */
-    [SIGNATURE_OFFSET] = LOW(0xface),
-    [SIGNATURE_OFFSET + 1] = HIGH(0xface),
-    /* End of boot sector marker */
-    [0x1FE] = 0x55,
-    [0x1FF] = 0xAA,
-};
-
-static const char *disk = "tests/acpi-test-disk.raw";
-static const char *data_dir = "tests/acpi-test-data";
-#ifdef CONFIG_IASL
-static const char *iasl = stringify(CONFIG_IASL);
-#else
-static const char *iasl;
-#endif
-
-static void free_test_data(test_data *data)
-{
-    AcpiSdtTable *temp;
-    int i;
-
-    if (data->rsdt_tables_addr) {
-        g_free(data->rsdt_tables_addr);
-    }
-
-    for (i = 0; i < data->tables->len; ++i) {
-        temp = &g_array_index(data->tables, AcpiSdtTable, i);
-        if (temp->aml) {
-            g_free(temp->aml);
-        }
-        if (temp->aml_file) {
-            if (!temp->tmp_files_retain &&
-                g_strstr_len(temp->aml_file, -1, "aml-")) {
-                unlink(temp->aml_file);
-            }
-            g_free(temp->aml_file);
-        }
-        if (temp->asl) {
-            g_free(temp->asl);
-        }
-        if (temp->asl_file) {
-            if (!temp->tmp_files_retain) {
-                unlink(temp->asl_file);
-            }
-            g_free(temp->asl_file);
-        }
-    }
-
-    g_array_free(data->tables, false);
-}
-
-static uint8_t acpi_checksum(const uint8_t *data, int len)
-{
-    int i;
-    uint8_t sum = 0;
-
-    for (i = 0; i < len; i++) {
-        sum += data[i];
-    }
-
-    return sum;
-}
-
-static void test_acpi_rsdp_address(test_data *data)
-{
-    uint32_t off;
-
-    /* OK, now find RSDP */
-    for (off = 0xf0000; off < 0x100000; off += 0x10) {
-        uint8_t sig[] = "RSD PTR ";
-        int i;
-
-        for (i = 0; i < sizeof sig - 1; ++i) {
-            sig[i] = readb(off + i);
-        }
-
-        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
-            break;
-        }
-    }
-
-    g_assert_cmphex(off, <, 0x100000);
-    data->rsdp_addr = off;
-}
-
-static void test_acpi_rsdp_table(test_data *data)
-{
-    AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table;
-    uint32_t addr = data->rsdp_addr;
-
-    ACPI_READ_FIELD(rsdp_table->signature, addr);
-    ACPI_ASSERT_CMP64(rsdp_table->signature, "RSD PTR ");
-
-    ACPI_READ_FIELD(rsdp_table->checksum, addr);
-    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
-    ACPI_READ_FIELD(rsdp_table->revision, addr);
-    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
-    ACPI_READ_FIELD(rsdp_table->length, addr);
-
-    /* rsdp checksum is not for the whole table, but for the first 20 bytes */
-    g_assert(!acpi_checksum((uint8_t *)rsdp_table, 20));
-}
-
-static void test_acpi_rsdt_table(test_data *data)
-{
-    AcpiRsdtDescriptorRev1 *rsdt_table = &data->rsdt_table;
-    uint32_t addr = data->rsdp_table.rsdt_physical_address;
-    uint32_t *tables;
-    int tables_nr;
-    uint8_t checksum;
-
-    /* read the header */
-    ACPI_READ_TABLE_HEADER(rsdt_table, addr);
-    ACPI_ASSERT_CMP(rsdt_table->signature, "RSDT");
-
-    /* compute the table entries in rsdt */
-    tables_nr = (rsdt_table->length - sizeof(AcpiRsdtDescriptorRev1)) /
-                sizeof(uint32_t);
-    g_assert_cmpint(tables_nr, >, 0);
-
-    /* get the addresses of the tables pointed by rsdt */
-    tables = g_new0(uint32_t, tables_nr);
-    ACPI_READ_ARRAY_PTR(tables, tables_nr, addr);
-
-    checksum = acpi_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
-               acpi_checksum((uint8_t *)tables, tables_nr * sizeof(uint32_t));
-    g_assert(!checksum);
-
-   /* SSDT tables after FADT */
-    data->rsdt_tables_addr = tables;
-    data->rsdt_tables_nr = tables_nr;
-}
-
-static void test_acpi_fadt_table(test_data *data)
-{
-    AcpiFadtDescriptorRev1 *fadt_table = &data->fadt_table;
-    uint32_t addr;
-
-    /* FADT table comes first */
-    addr = data->rsdt_tables_addr[0];
-    ACPI_READ_TABLE_HEADER(fadt_table, addr);
-
-    ACPI_READ_FIELD(fadt_table->firmware_ctrl, addr);
-    ACPI_READ_FIELD(fadt_table->dsdt, addr);
-    ACPI_READ_FIELD(fadt_table->model, addr);
-    ACPI_READ_FIELD(fadt_table->reserved1, addr);
-    ACPI_READ_FIELD(fadt_table->sci_int, addr);
-    ACPI_READ_FIELD(fadt_table->smi_cmd, addr);
-    ACPI_READ_FIELD(fadt_table->acpi_enable, addr);
-    ACPI_READ_FIELD(fadt_table->acpi_disable, addr);
-    ACPI_READ_FIELD(fadt_table->S4bios_req, addr);
-    ACPI_READ_FIELD(fadt_table->reserved2, addr);
-    ACPI_READ_FIELD(fadt_table->pm1a_evt_blk, addr);
-    ACPI_READ_FIELD(fadt_table->pm1b_evt_blk, addr);
-    ACPI_READ_FIELD(fadt_table->pm1a_cnt_blk, addr);
-    ACPI_READ_FIELD(fadt_table->pm1b_cnt_blk, addr);
-    ACPI_READ_FIELD(fadt_table->pm2_cnt_blk, addr);
-    ACPI_READ_FIELD(fadt_table->pm_tmr_blk, addr);
-    ACPI_READ_FIELD(fadt_table->gpe0_blk, addr);
-    ACPI_READ_FIELD(fadt_table->gpe1_blk, addr);
-    ACPI_READ_FIELD(fadt_table->pm1_evt_len, addr);
-    ACPI_READ_FIELD(fadt_table->pm1_cnt_len, addr);
-    ACPI_READ_FIELD(fadt_table->pm2_cnt_len, addr);
-    ACPI_READ_FIELD(fadt_table->pm_tmr_len, addr);
-    ACPI_READ_FIELD(fadt_table->gpe0_blk_len, addr);
-    ACPI_READ_FIELD(fadt_table->gpe1_blk_len, addr);
-    ACPI_READ_FIELD(fadt_table->gpe1_base, addr);
-    ACPI_READ_FIELD(fadt_table->reserved3, addr);
-    ACPI_READ_FIELD(fadt_table->plvl2_lat, addr);
-    ACPI_READ_FIELD(fadt_table->plvl3_lat, addr);
-    ACPI_READ_FIELD(fadt_table->flush_size, addr);
-    ACPI_READ_FIELD(fadt_table->flush_stride, addr);
-    ACPI_READ_FIELD(fadt_table->duty_offset, addr);
-    ACPI_READ_FIELD(fadt_table->duty_width, addr);
-    ACPI_READ_FIELD(fadt_table->day_alrm, addr);
-    ACPI_READ_FIELD(fadt_table->mon_alrm, addr);
-    ACPI_READ_FIELD(fadt_table->century, addr);
-    ACPI_READ_FIELD(fadt_table->reserved4, addr);
-    ACPI_READ_FIELD(fadt_table->reserved4a, addr);
-    ACPI_READ_FIELD(fadt_table->reserved4b, addr);
-    ACPI_READ_FIELD(fadt_table->flags, addr);
-
-    ACPI_ASSERT_CMP(fadt_table->signature, "FACP");
-    g_assert(!acpi_checksum((uint8_t *)fadt_table, fadt_table->length));
-}
-
-static void test_acpi_facs_table(test_data *data)
-{
-    AcpiFacsDescriptorRev1 *facs_table = &data->facs_table;
-    uint32_t addr = data->fadt_table.firmware_ctrl;
-
-    ACPI_READ_FIELD(facs_table->signature, addr);
-    ACPI_READ_FIELD(facs_table->length, addr);
-    ACPI_READ_FIELD(facs_table->hardware_signature, addr);
-    ACPI_READ_FIELD(facs_table->firmware_waking_vector, addr);
-    ACPI_READ_FIELD(facs_table->global_lock, addr);
-    ACPI_READ_FIELD(facs_table->flags, addr);
-    ACPI_READ_ARRAY(facs_table->resverved3, addr);
-
-    ACPI_ASSERT_CMP(facs_table->signature, "FACS");
-}
-
-static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
-{
-    uint8_t checksum;
-
-    ACPI_READ_TABLE_HEADER(&sdt_table->header, addr);
-
-    sdt_table->aml_len = sdt_table->header.length - sizeof(AcpiTableHeader);
-    sdt_table->aml = g_malloc0(sdt_table->aml_len);
-    ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
-
-    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
-               acpi_checksum((uint8_t *)sdt_table->aml, sdt_table->aml_len);
-    g_assert(!checksum);
-}
-
-static void test_acpi_dsdt_table(test_data *data)
-{
-    AcpiSdtTable dsdt_table;
-    uint32_t addr = data->fadt_table.dsdt;
-
-    memset(&dsdt_table, 0, sizeof(dsdt_table));
-    data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
-
-    test_dst_table(&dsdt_table, addr);
-    ACPI_ASSERT_CMP(dsdt_table.header.signature, "DSDT");
-
-    /* Place DSDT first */
-    g_array_append_val(data->tables, dsdt_table);
-}
-
-static void test_acpi_tables(test_data *data)
-{
-    int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
-    int i;
-
-    for (i = 0; i < tables_nr; i++) {
-        AcpiSdtTable ssdt_table;
-
-        memset(&ssdt_table, 0 , sizeof(ssdt_table));
-        uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
-        test_dst_table(&ssdt_table, addr);
-        g_array_append_val(data->tables, ssdt_table);
-    }
-}
-
-static void dump_aml_files(test_data *data, bool rebuild)
-{
-    AcpiSdtTable *sdt;
-    GError *error = NULL;
-    gchar *aml_file = NULL;
-    gint fd;
-    ssize_t ret;
-    int i;
-
-    for (i = 0; i < data->tables->len; ++i) {
-        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
-        g_assert(sdt->aml);
-
-        if (rebuild) {
-            uint32_t signature = cpu_to_le32(sdt->header.signature);
-            aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
-                                       (gchar *)&signature);
-            fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
-                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
-        } else {
-            fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
-            g_assert_no_error(error);
-        }
-        g_assert(fd >= 0);
-
-        ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader));
-        g_assert(ret == sizeof(AcpiTableHeader));
-        ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
-        g_assert(ret == sdt->aml_len);
-
-        close(fd);
-
-        if (aml_file) {
-            g_free(aml_file);
-        }
-    }
-}
-
-static bool compare_signature(AcpiSdtTable *sdt, const char *signature)
-{
-   return !memcmp(&sdt->header.signature, signature, 4);
-}
-
-static bool load_asl(GArray *sdts, AcpiSdtTable *sdt)
-{
-    AcpiSdtTable *temp;
-    GError *error = NULL;
-    GString *command_line = g_string_new(iasl);
-    gint fd;
-    gchar *out, *out_err;
-    gboolean ret;
-    int i;
-
-    fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error);
-    g_assert_no_error(error);
-    close(fd);
-
-    /* build command line */
-    g_string_append_printf(command_line, " -p %s ", sdt->asl_file);
-    if (compare_signature(sdt, "DSDT") ||
-        compare_signature(sdt, "SSDT")) {
-        for (i = 0; i < sdts->len; ++i) {
-            temp = &g_array_index(sdts, AcpiSdtTable, i);
-            if (compare_signature(temp, "DSDT") ||
-                compare_signature(temp, "SSDT")) {
-                g_string_append_printf(command_line, "-e %s ", temp->aml_file);
-            }
-        }
-    }
-    g_string_append_printf(command_line, "-d %s", sdt->aml_file);
-
-    /* pass 'out' and 'out_err' in order to be redirected */
-    ret = g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error);
-    g_assert_no_error(error);
-    if (ret) {
-        ret = g_file_get_contents(sdt->asl_file, (gchar **)&sdt->asl,
-                                  &sdt->asl_len, &error);
-        g_assert(ret);
-        g_assert_no_error(error);
-        ret = (sdt->asl_len > 0);
-    }
-
-    g_free(out);
-    g_free(out_err);
-    g_string_free(command_line, true);
-
-    return !ret;
-}
-
-#define COMMENT_END "*/"
-#define DEF_BLOCK "DefinitionBlock ("
-#define BLOCK_NAME_END ".aml"
-
-static GString *normalize_asl(gchar *asl_code)
-{
-    GString *asl = g_string_new(asl_code);
-    gchar *comment, *block_name;
-
-    /* strip comments (different generation days) */
-    comment = g_strstr_len(asl->str, asl->len, COMMENT_END);
-    if (comment) {
-        asl = g_string_erase(asl, 0, comment + sizeof(COMMENT_END) - asl->str);
-    }
-
-    /* strip def block name (it has file path in it) */
-    if (g_str_has_prefix(asl->str, DEF_BLOCK)) {
-        block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END);
-        g_assert(block_name);
-        asl = g_string_erase(asl, 0,
-                             block_name + sizeof(BLOCK_NAME_END) - asl->str);
-    }
-
-    return asl;
-}
-
-static GArray *load_expected_aml(test_data *data)
-{
-    int i;
-    AcpiSdtTable *sdt;
-    gchar *aml_file;
-    GError *error = NULL;
-    gboolean ret;
-
-    GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
-    for (i = 0; i < data->tables->len; ++i) {
-        AcpiSdtTable exp_sdt;
-        uint32_t signature;
-
-        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
-
-        memset(&exp_sdt, 0, sizeof(exp_sdt));
-        exp_sdt.header.signature = sdt->header.signature;
-
-        signature = cpu_to_le32(sdt->header.signature);
-        aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
-                                   (gchar *)&signature);
-        exp_sdt.aml_file = aml_file;
-        g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
-        ret = g_file_get_contents(aml_file, &exp_sdt.aml,
-                                  &exp_sdt.aml_len, &error);
-        g_assert(ret);
-        g_assert_no_error(error);
-        g_assert(exp_sdt.aml);
-        g_assert(exp_sdt.aml_len);
-
-        g_array_append_val(exp_tables, exp_sdt);
-    }
-
-    return exp_tables;
-}
-
-static void test_acpi_asl(test_data *data)
-{
-    int i;
-    AcpiSdtTable *sdt, *exp_sdt;
-    test_data exp_data;
-    gboolean exp_err, err;
-
-    memset(&exp_data, 0, sizeof(exp_data));
-    exp_data.tables = load_expected_aml(data);
-    dump_aml_files(data, false);
-    for (i = 0; i < data->tables->len; ++i) {
-        GString *asl, *exp_asl;
-
-        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
-        exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
-
-        err = load_asl(data->tables, sdt);
-        asl = normalize_asl(sdt->asl);
-
-        exp_err = load_asl(exp_data.tables, exp_sdt);
-        exp_asl = normalize_asl(exp_sdt->asl);
-
-        /* TODO: check for warnings */
-        g_assert(!err || exp_err);
-
-        if (g_strcmp0(asl->str, exp_asl->str)) {
-            if (exp_err) {
-                fprintf(stderr,
-                        "Warning! iasl couldn't parse the expected aml\n");
-            } else {
-                uint32_t signature = cpu_to_le32(exp_sdt->header.signature);
-                sdt->tmp_files_retain = true;
-                exp_sdt->tmp_files_retain = true;
-                fprintf(stderr,
-                        "acpi-test: Warning! %.4s mismatch. "
-                        "Actual [asl:%s, aml:%s], Expected [asl:%s, aml:%s].\n",
-                        (gchar *)&signature,
-                        sdt->asl_file, sdt->aml_file,
-                        exp_sdt->asl_file, exp_sdt->aml_file);
-          }
-        }
-        g_string_free(asl, true);
-        g_string_free(exp_asl, true);
-    }
-
-    free_test_data(&exp_data);
-}
-
-static void test_acpi_one(const char *params, test_data *data)
-{
-    char *args;
-    uint8_t signature_low;
-    uint8_t signature_high;
-    uint16_t signature;
-    int i;
-    const char *device = "";
-
-    if (!g_strcmp0(data->machine, MACHINE_Q35)) {
-        device = ",id=hd -device ide-hd,drive=hd";
-    }
-
-    args = g_strdup_printf("-net none -display none %s -drive file=%s%s,",
-                           params ? params : "", disk, device);
-    qtest_start(args);
-
-   /* Wait at most 1 minute */
-#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
-#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
-
-    /* Poll until code has run and modified memory.  Once it has we know BIOS
-     * initialization is done.  TODO: check that IP reached the halt
-     * instruction.
-     */
-    for (i = 0; i < TEST_CYCLES; ++i) {
-        signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
-        signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
-        signature = (signature_high << 8) | signature_low;
-        if (signature == SIGNATURE) {
-            break;
-        }
-        g_usleep(TEST_DELAY);
-    }
-    g_assert_cmphex(signature, ==, SIGNATURE);
-
-    test_acpi_rsdp_address(data);
-    test_acpi_rsdp_table(data);
-    test_acpi_rsdt_table(data);
-    test_acpi_fadt_table(data);
-    test_acpi_facs_table(data);
-    test_acpi_dsdt_table(data);
-    test_acpi_tables(data);
-
-    if (iasl) {
-        if (getenv(ACPI_REBUILD_EXPECTED_AML)) {
-            dump_aml_files(data, true);
-        } else {
-            test_acpi_asl(data);
-        }
-    }
-
-    qtest_quit(global_qtest);
-    g_free(args);
-}
-
-static void test_acpi_tcg(void)
-{
-    test_data data;
-
-    /* Supplying -machine accel argument overrides the default (qtest).
-     * This is to make guest actually run.
-     */
-    memset(&data, 0, sizeof(data));
-    data.machine = MACHINE_PC;
-    test_acpi_one("-machine accel=tcg", &data);
-    free_test_data(&data);
-
-    memset(&data, 0, sizeof(data));
-    data.machine = MACHINE_Q35;
-    test_acpi_one("-machine q35,accel=tcg", &data);
-    free_test_data(&data);
-}
-
-int main(int argc, char *argv[])
-{
-    const char *arch = qtest_get_arch();
-    FILE *f = fopen(disk, "w");
-    int ret;
-    fwrite(boot_sector, 1, sizeof boot_sector, f);
-    fclose(f);
-
-    g_test_init(&argc, &argv, NULL);
-
-    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
-        qtest_add_func("acpi/tcg", test_acpi_tcg);
-    }
-    ret = g_test_run();
-    unlink(disk);
-    return ret;
-}
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
new file mode 100644 (file)
index 0000000..62771f7
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+ * Boot order test cases.
+ *
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Authors:
+ *  Michael S. Tsirkin <mst@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include "qemu-common.h"
+#include "libqtest.h"
+#include "qemu/compiler.h"
+#include "hw/i386/acpi-defs.h"
+#include "hw/i386/smbios.h"
+#include "qemu/bitmap.h"
+
+#define MACHINE_PC "pc"
+#define MACHINE_Q35 "q35"
+
+#define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
+
+/* DSDT and SSDTs format */
+typedef struct {
+    AcpiTableHeader header;
+    gchar *aml;            /* aml bytecode from guest */
+    gsize aml_len;
+    gchar *aml_file;
+    gchar *asl;            /* asl code generated from aml */
+    gsize asl_len;
+    gchar *asl_file;
+    bool tmp_files_retain;   /* do not delete the temp asl/aml */
+} QEMU_PACKED AcpiSdtTable;
+
+typedef struct {
+    const char *machine;
+    uint32_t rsdp_addr;
+    AcpiRsdpDescriptor rsdp_table;
+    AcpiRsdtDescriptorRev1 rsdt_table;
+    AcpiFadtDescriptorRev1 fadt_table;
+    AcpiFacsDescriptorRev1 facs_table;
+    uint32_t *rsdt_tables_addr;
+    int rsdt_tables_nr;
+    GArray *tables;
+    uint32_t smbios_ep_addr;
+    struct smbios_entry_point smbios_ep_table;
+} test_data;
+
+#define LOW(x) ((x) & 0xff)
+#define HIGH(x) ((x) >> 8)
+
+#define SIGNATURE 0xdead
+#define SIGNATURE_OFFSET 0x10
+#define BOOT_SECTOR_ADDRESS 0x7c00
+
+#define ACPI_READ_FIELD(field, addr)           \
+    do {                                       \
+        switch (sizeof(field)) {               \
+        case 1:                                \
+            field = readb(addr);               \
+            break;                             \
+        case 2:                                \
+            field = readw(addr);               \
+            break;                             \
+        case 4:                                \
+            field = readl(addr);               \
+            break;                             \
+        case 8:                                \
+            field = readq(addr);               \
+            break;                             \
+        default:                               \
+            g_assert(false);                   \
+        }                                      \
+        addr += sizeof(field);                  \
+    } while (0);
+
+#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
+    do {                                        \
+        int idx;                                \
+        for (idx = 0; idx < length; ++idx) {    \
+            ACPI_READ_FIELD(arr[idx], addr);    \
+        }                                       \
+    } while (0);
+
+#define ACPI_READ_ARRAY(arr, addr)                               \
+    ACPI_READ_ARRAY_PTR(arr, sizeof(arr)/sizeof(arr[0]), addr)
+
+#define ACPI_READ_TABLE_HEADER(table, addr)                      \
+    do {                                                         \
+        ACPI_READ_FIELD((table)->signature, addr);               \
+        ACPI_READ_FIELD((table)->length, addr);                  \
+        ACPI_READ_FIELD((table)->revision, addr);                \
+        ACPI_READ_FIELD((table)->checksum, addr);                \
+        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
+        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
+        ACPI_READ_FIELD((table)->oem_revision, addr);            \
+        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
+        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
+    } while (0);
+
+#define ACPI_ASSERT_CMP(actual, expected) do { \
+    uint32_t ACPI_ASSERT_CMP_le = cpu_to_le32(actual); \
+    char ACPI_ASSERT_CMP_str[5] = {}; \
+    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 4); \
+    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
+} while (0)
+
+#define ACPI_ASSERT_CMP64(actual, expected) do { \
+    uint64_t ACPI_ASSERT_CMP_le = cpu_to_le64(actual); \
+    char ACPI_ASSERT_CMP_str[9] = {}; \
+    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 8); \
+    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
+} while (0)
+
+/* Boot sector code: write SIGNATURE into memory,
+ * then halt.
+ * Q35 machine requires a minimum 0x7e000 bytes disk.
+ * (bug or feature?)
+ */
+static uint8_t boot_sector[0x7e000] = {
+    /* 7c00: mov $0xdead,%ax */
+    [0x00] = 0xb8,
+    [0x01] = LOW(SIGNATURE),
+    [0x02] = HIGH(SIGNATURE),
+    /* 7c03:  mov %ax,0x7c10 */
+    [0x03] = 0xa3,
+    [0x04] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
+    [0x05] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
+    /* 7c06: cli */
+    [0x06] = 0xfa,
+    /* 7c07: hlt */
+    [0x07] = 0xf4,
+    /* 7c08: jmp 0x7c07=0x7c0a-3 */
+    [0x08] = 0xeb,
+    [0x09] = LOW(-3),
+    /* We mov 0xdead here: set value to make debugging easier */
+    [SIGNATURE_OFFSET] = LOW(0xface),
+    [SIGNATURE_OFFSET + 1] = HIGH(0xface),
+    /* End of boot sector marker */
+    [0x1FE] = 0x55,
+    [0x1FF] = 0xAA,
+};
+
+static const char *disk = "tests/acpi-test-disk.raw";
+static const char *data_dir = "tests/acpi-test-data";
+#ifdef CONFIG_IASL
+static const char *iasl = stringify(CONFIG_IASL);
+#else
+static const char *iasl;
+#endif
+
+static void free_test_data(test_data *data)
+{
+    AcpiSdtTable *temp;
+    int i;
+
+    if (data->rsdt_tables_addr) {
+        g_free(data->rsdt_tables_addr);
+    }
+
+    for (i = 0; i < data->tables->len; ++i) {
+        temp = &g_array_index(data->tables, AcpiSdtTable, i);
+        if (temp->aml) {
+            g_free(temp->aml);
+        }
+        if (temp->aml_file) {
+            if (!temp->tmp_files_retain &&
+                g_strstr_len(temp->aml_file, -1, "aml-")) {
+                unlink(temp->aml_file);
+            }
+            g_free(temp->aml_file);
+        }
+        if (temp->asl) {
+            g_free(temp->asl);
+        }
+        if (temp->asl_file) {
+            if (!temp->tmp_files_retain) {
+                unlink(temp->asl_file);
+            }
+            g_free(temp->asl_file);
+        }
+    }
+
+    g_array_free(data->tables, false);
+}
+
+static uint8_t acpi_checksum(const uint8_t *data, int len)
+{
+    int i;
+    uint8_t sum = 0;
+
+    for (i = 0; i < len; i++) {
+        sum += data[i];
+    }
+
+    return sum;
+}
+
+static void test_acpi_rsdp_address(test_data *data)
+{
+    uint32_t off;
+
+    /* OK, now find RSDP */
+    for (off = 0xf0000; off < 0x100000; off += 0x10) {
+        uint8_t sig[] = "RSD PTR ";
+        int i;
+
+        for (i = 0; i < sizeof sig - 1; ++i) {
+            sig[i] = readb(off + i);
+        }
+
+        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
+            break;
+        }
+    }
+
+    g_assert_cmphex(off, <, 0x100000);
+    data->rsdp_addr = off;
+}
+
+static void test_acpi_rsdp_table(test_data *data)
+{
+    AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table;
+    uint32_t addr = data->rsdp_addr;
+
+    ACPI_READ_FIELD(rsdp_table->signature, addr);
+    ACPI_ASSERT_CMP64(rsdp_table->signature, "RSD PTR ");
+
+    ACPI_READ_FIELD(rsdp_table->checksum, addr);
+    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
+    ACPI_READ_FIELD(rsdp_table->revision, addr);
+    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
+    ACPI_READ_FIELD(rsdp_table->length, addr);
+
+    /* rsdp checksum is not for the whole table, but for the first 20 bytes */
+    g_assert(!acpi_checksum((uint8_t *)rsdp_table, 20));
+}
+
+static void test_acpi_rsdt_table(test_data *data)
+{
+    AcpiRsdtDescriptorRev1 *rsdt_table = &data->rsdt_table;
+    uint32_t addr = data->rsdp_table.rsdt_physical_address;
+    uint32_t *tables;
+    int tables_nr;
+    uint8_t checksum;
+
+    /* read the header */
+    ACPI_READ_TABLE_HEADER(rsdt_table, addr);
+    ACPI_ASSERT_CMP(rsdt_table->signature, "RSDT");
+
+    /* compute the table entries in rsdt */
+    tables_nr = (rsdt_table->length - sizeof(AcpiRsdtDescriptorRev1)) /
+                sizeof(uint32_t);
+    g_assert_cmpint(tables_nr, >, 0);
+
+    /* get the addresses of the tables pointed by rsdt */
+    tables = g_new0(uint32_t, tables_nr);
+    ACPI_READ_ARRAY_PTR(tables, tables_nr, addr);
+
+    checksum = acpi_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
+               acpi_checksum((uint8_t *)tables, tables_nr * sizeof(uint32_t));
+    g_assert(!checksum);
+
+   /* SSDT tables after FADT */
+    data->rsdt_tables_addr = tables;
+    data->rsdt_tables_nr = tables_nr;
+}
+
+static void test_acpi_fadt_table(test_data *data)
+{
+    AcpiFadtDescriptorRev1 *fadt_table = &data->fadt_table;
+    uint32_t addr;
+
+    /* FADT table comes first */
+    addr = data->rsdt_tables_addr[0];
+    ACPI_READ_TABLE_HEADER(fadt_table, addr);
+
+    ACPI_READ_FIELD(fadt_table->firmware_ctrl, addr);
+    ACPI_READ_FIELD(fadt_table->dsdt, addr);
+    ACPI_READ_FIELD(fadt_table->model, addr);
+    ACPI_READ_FIELD(fadt_table->reserved1, addr);
+    ACPI_READ_FIELD(fadt_table->sci_int, addr);
+    ACPI_READ_FIELD(fadt_table->smi_cmd, addr);
+    ACPI_READ_FIELD(fadt_table->acpi_enable, addr);
+    ACPI_READ_FIELD(fadt_table->acpi_disable, addr);
+    ACPI_READ_FIELD(fadt_table->S4bios_req, addr);
+    ACPI_READ_FIELD(fadt_table->reserved2, addr);
+    ACPI_READ_FIELD(fadt_table->pm1a_evt_blk, addr);
+    ACPI_READ_FIELD(fadt_table->pm1b_evt_blk, addr);
+    ACPI_READ_FIELD(fadt_table->pm1a_cnt_blk, addr);
+    ACPI_READ_FIELD(fadt_table->pm1b_cnt_blk, addr);
+    ACPI_READ_FIELD(fadt_table->pm2_cnt_blk, addr);
+    ACPI_READ_FIELD(fadt_table->pm_tmr_blk, addr);
+    ACPI_READ_FIELD(fadt_table->gpe0_blk, addr);
+    ACPI_READ_FIELD(fadt_table->gpe1_blk, addr);
+    ACPI_READ_FIELD(fadt_table->pm1_evt_len, addr);
+    ACPI_READ_FIELD(fadt_table->pm1_cnt_len, addr);
+    ACPI_READ_FIELD(fadt_table->pm2_cnt_len, addr);
+    ACPI_READ_FIELD(fadt_table->pm_tmr_len, addr);
+    ACPI_READ_FIELD(fadt_table->gpe0_blk_len, addr);
+    ACPI_READ_FIELD(fadt_table->gpe1_blk_len, addr);
+    ACPI_READ_FIELD(fadt_table->gpe1_base, addr);
+    ACPI_READ_FIELD(fadt_table->reserved3, addr);
+    ACPI_READ_FIELD(fadt_table->plvl2_lat, addr);
+    ACPI_READ_FIELD(fadt_table->plvl3_lat, addr);
+    ACPI_READ_FIELD(fadt_table->flush_size, addr);
+    ACPI_READ_FIELD(fadt_table->flush_stride, addr);
+    ACPI_READ_FIELD(fadt_table->duty_offset, addr);
+    ACPI_READ_FIELD(fadt_table->duty_width, addr);
+    ACPI_READ_FIELD(fadt_table->day_alrm, addr);
+    ACPI_READ_FIELD(fadt_table->mon_alrm, addr);
+    ACPI_READ_FIELD(fadt_table->century, addr);
+    ACPI_READ_FIELD(fadt_table->reserved4, addr);
+    ACPI_READ_FIELD(fadt_table->reserved4a, addr);
+    ACPI_READ_FIELD(fadt_table->reserved4b, addr);
+    ACPI_READ_FIELD(fadt_table->flags, addr);
+
+    ACPI_ASSERT_CMP(fadt_table->signature, "FACP");
+    g_assert(!acpi_checksum((uint8_t *)fadt_table, fadt_table->length));
+}
+
+static void test_acpi_facs_table(test_data *data)
+{
+    AcpiFacsDescriptorRev1 *facs_table = &data->facs_table;
+    uint32_t addr = data->fadt_table.firmware_ctrl;
+
+    ACPI_READ_FIELD(facs_table->signature, addr);
+    ACPI_READ_FIELD(facs_table->length, addr);
+    ACPI_READ_FIELD(facs_table->hardware_signature, addr);
+    ACPI_READ_FIELD(facs_table->firmware_waking_vector, addr);
+    ACPI_READ_FIELD(facs_table->global_lock, addr);
+    ACPI_READ_FIELD(facs_table->flags, addr);
+    ACPI_READ_ARRAY(facs_table->resverved3, addr);
+
+    ACPI_ASSERT_CMP(facs_table->signature, "FACS");
+}
+
+static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
+{
+    uint8_t checksum;
+
+    ACPI_READ_TABLE_HEADER(&sdt_table->header, addr);
+
+    sdt_table->aml_len = sdt_table->header.length - sizeof(AcpiTableHeader);
+    sdt_table->aml = g_malloc0(sdt_table->aml_len);
+    ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
+
+    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
+               acpi_checksum((uint8_t *)sdt_table->aml, sdt_table->aml_len);
+    g_assert(!checksum);
+}
+
+static void test_acpi_dsdt_table(test_data *data)
+{
+    AcpiSdtTable dsdt_table;
+    uint32_t addr = data->fadt_table.dsdt;
+
+    memset(&dsdt_table, 0, sizeof(dsdt_table));
+    data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
+
+    test_dst_table(&dsdt_table, addr);
+    ACPI_ASSERT_CMP(dsdt_table.header.signature, "DSDT");
+
+    /* Place DSDT first */
+    g_array_append_val(data->tables, dsdt_table);
+}
+
+static void test_acpi_tables(test_data *data)
+{
+    int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
+    int i;
+
+    for (i = 0; i < tables_nr; i++) {
+        AcpiSdtTable ssdt_table;
+
+        memset(&ssdt_table, 0 , sizeof(ssdt_table));
+        uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
+        test_dst_table(&ssdt_table, addr);
+        g_array_append_val(data->tables, ssdt_table);
+    }
+}
+
+static void dump_aml_files(test_data *data, bool rebuild)
+{
+    AcpiSdtTable *sdt;
+    GError *error = NULL;
+    gchar *aml_file = NULL;
+    gint fd;
+    ssize_t ret;
+    int i;
+
+    for (i = 0; i < data->tables->len; ++i) {
+        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
+        g_assert(sdt->aml);
+
+        if (rebuild) {
+            uint32_t signature = cpu_to_le32(sdt->header.signature);
+            aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
+                                       (gchar *)&signature);
+            fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
+                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+        } else {
+            fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
+            g_assert_no_error(error);
+        }
+        g_assert(fd >= 0);
+
+        ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader));
+        g_assert(ret == sizeof(AcpiTableHeader));
+        ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
+        g_assert(ret == sdt->aml_len);
+
+        close(fd);
+
+        if (aml_file) {
+            g_free(aml_file);
+        }
+    }
+}
+
+static bool compare_signature(AcpiSdtTable *sdt, const char *signature)
+{
+   return !memcmp(&sdt->header.signature, signature, 4);
+}
+
+static bool load_asl(GArray *sdts, AcpiSdtTable *sdt)
+{
+    AcpiSdtTable *temp;
+    GError *error = NULL;
+    GString *command_line = g_string_new(iasl);
+    gint fd;
+    gchar *out, *out_err;
+    gboolean ret;
+    int i;
+
+    fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error);
+    g_assert_no_error(error);
+    close(fd);
+
+    /* build command line */
+    g_string_append_printf(command_line, " -p %s ", sdt->asl_file);
+    if (compare_signature(sdt, "DSDT") ||
+        compare_signature(sdt, "SSDT")) {
+        for (i = 0; i < sdts->len; ++i) {
+            temp = &g_array_index(sdts, AcpiSdtTable, i);
+            if (compare_signature(temp, "DSDT") ||
+                compare_signature(temp, "SSDT")) {
+                g_string_append_printf(command_line, "-e %s ", temp->aml_file);
+            }
+        }
+    }
+    g_string_append_printf(command_line, "-d %s", sdt->aml_file);
+
+    /* pass 'out' and 'out_err' in order to be redirected */
+    ret = g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error);
+    g_assert_no_error(error);
+    if (ret) {
+        ret = g_file_get_contents(sdt->asl_file, (gchar **)&sdt->asl,
+                                  &sdt->asl_len, &error);
+        g_assert(ret);
+        g_assert_no_error(error);
+        ret = (sdt->asl_len > 0);
+    }
+
+    g_free(out);
+    g_free(out_err);
+    g_string_free(command_line, true);
+
+    return !ret;
+}
+
+#define COMMENT_END "*/"
+#define DEF_BLOCK "DefinitionBlock ("
+#define BLOCK_NAME_END ".aml"
+
+static GString *normalize_asl(gchar *asl_code)
+{
+    GString *asl = g_string_new(asl_code);
+    gchar *comment, *block_name;
+
+    /* strip comments (different generation days) */
+    comment = g_strstr_len(asl->str, asl->len, COMMENT_END);
+    if (comment) {
+        asl = g_string_erase(asl, 0, comment + sizeof(COMMENT_END) - asl->str);
+    }
+
+    /* strip def block name (it has file path in it) */
+    if (g_str_has_prefix(asl->str, DEF_BLOCK)) {
+        block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END);
+        g_assert(block_name);
+        asl = g_string_erase(asl, 0,
+                             block_name + sizeof(BLOCK_NAME_END) - asl->str);
+    }
+
+    return asl;
+}
+
+static GArray *load_expected_aml(test_data *data)
+{
+    int i;
+    AcpiSdtTable *sdt;
+    gchar *aml_file;
+    GError *error = NULL;
+    gboolean ret;
+
+    GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
+    for (i = 0; i < data->tables->len; ++i) {
+        AcpiSdtTable exp_sdt;
+        uint32_t signature;
+
+        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
+
+        memset(&exp_sdt, 0, sizeof(exp_sdt));
+        exp_sdt.header.signature = sdt->header.signature;
+
+        signature = cpu_to_le32(sdt->header.signature);
+        aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
+                                   (gchar *)&signature);
+        exp_sdt.aml_file = aml_file;
+        g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
+        ret = g_file_get_contents(aml_file, &exp_sdt.aml,
+                                  &exp_sdt.aml_len, &error);
+        g_assert(ret);
+        g_assert_no_error(error);
+        g_assert(exp_sdt.aml);
+        g_assert(exp_sdt.aml_len);
+
+        g_array_append_val(exp_tables, exp_sdt);
+    }
+
+    return exp_tables;
+}
+
+static void test_acpi_asl(test_data *data)
+{
+    int i;
+    AcpiSdtTable *sdt, *exp_sdt;
+    test_data exp_data;
+    gboolean exp_err, err;
+
+    memset(&exp_data, 0, sizeof(exp_data));
+    exp_data.tables = load_expected_aml(data);
+    dump_aml_files(data, false);
+    for (i = 0; i < data->tables->len; ++i) {
+        GString *asl, *exp_asl;
+
+        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
+        exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
+
+        err = load_asl(data->tables, sdt);
+        asl = normalize_asl(sdt->asl);
+
+        exp_err = load_asl(exp_data.tables, exp_sdt);
+        exp_asl = normalize_asl(exp_sdt->asl);
+
+        /* TODO: check for warnings */
+        g_assert(!err || exp_err);
+
+        if (g_strcmp0(asl->str, exp_asl->str)) {
+            if (exp_err) {
+                fprintf(stderr,
+                        "Warning! iasl couldn't parse the expected aml\n");
+            } else {
+                uint32_t signature = cpu_to_le32(exp_sdt->header.signature);
+                sdt->tmp_files_retain = true;
+                exp_sdt->tmp_files_retain = true;
+                fprintf(stderr,
+                        "acpi-test: Warning! %.4s mismatch. "
+                        "Actual [asl:%s, aml:%s], Expected [asl:%s, aml:%s].\n",
+                        (gchar *)&signature,
+                        sdt->asl_file, sdt->aml_file,
+                        exp_sdt->asl_file, exp_sdt->aml_file);
+          }
+        }
+        g_string_free(asl, true);
+        g_string_free(exp_asl, true);
+    }
+
+    free_test_data(&exp_data);
+}
+
+static void test_smbios_ep_address(test_data *data)
+{
+    uint32_t off;
+
+    /* find smbios entry point structure */
+    for (off = 0xf0000; off < 0x100000; off += 0x10) {
+        uint8_t sig[] = "_SM_";
+        int i;
+
+        for (i = 0; i < sizeof sig - 1; ++i) {
+            sig[i] = readb(off + i);
+        }
+
+        if (!memcmp(sig, "_SM_", sizeof sig)) {
+            break;
+        }
+    }
+
+    g_assert_cmphex(off, <, 0x100000);
+    data->smbios_ep_addr = off;
+}
+
+static void test_smbios_ep_table(test_data *data)
+{
+    struct smbios_entry_point *ep_table = &data->smbios_ep_table;
+    uint32_t addr = data->smbios_ep_addr;
+
+    ACPI_READ_ARRAY(ep_table->anchor_string, addr);
+    g_assert(!memcmp(ep_table->anchor_string, "_SM_", 4));
+    ACPI_READ_FIELD(ep_table->checksum, addr);
+    ACPI_READ_FIELD(ep_table->length, addr);
+    ACPI_READ_FIELD(ep_table->smbios_major_version, addr);
+    ACPI_READ_FIELD(ep_table->smbios_minor_version, addr);
+    ACPI_READ_FIELD(ep_table->max_structure_size, addr);
+    ACPI_READ_FIELD(ep_table->entry_point_revision, addr);
+    ACPI_READ_ARRAY(ep_table->formatted_area, addr);
+    ACPI_READ_ARRAY(ep_table->intermediate_anchor_string, addr);
+    g_assert(!memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5));
+    ACPI_READ_FIELD(ep_table->intermediate_checksum, addr);
+    ACPI_READ_FIELD(ep_table->structure_table_length, addr);
+    g_assert_cmpuint(ep_table->structure_table_length, >, 0);
+    ACPI_READ_FIELD(ep_table->structure_table_address, addr);
+    ACPI_READ_FIELD(ep_table->number_of_structures, addr);
+    g_assert_cmpuint(ep_table->number_of_structures, >, 0);
+    ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
+    g_assert(!acpi_checksum((uint8_t *)ep_table, sizeof *ep_table));
+    g_assert(!acpi_checksum((uint8_t *)ep_table + 0x10,
+                            sizeof *ep_table - 0x10));
+}
+
+static inline bool smbios_single_instance(uint8_t type)
+{
+    switch (type) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 16:
+    case 32:
+    case 127:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static void test_smbios_structs(test_data *data)
+{
+    DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 };
+    struct smbios_entry_point *ep_table = &data->smbios_ep_table;
+    uint32_t addr = ep_table->structure_table_address;
+    int i, len, max_len = 0;
+    uint8_t type, prv, crt;
+    uint8_t required_struct_types[] = {0, 1, 3, 4, 16, 17, 19, 32, 127};
+
+    /* walk the smbios tables */
+    for (i = 0; i < ep_table->number_of_structures; i++) {
+
+        /* grab type and formatted area length from struct header */
+        type = readb(addr);
+        g_assert_cmpuint(type, <=, SMBIOS_MAX_TYPE);
+        len = readb(addr + 1);
+
+        /* single-instance structs must not have been encountered before */
+        if (smbios_single_instance(type)) {
+            g_assert(!test_bit(type, struct_bitmap));
+        }
+        set_bit(type, struct_bitmap);
+
+        /* seek to end of unformatted string area of this struct ("\0\0") */
+        prv = crt = 1;
+        while (prv || crt) {
+            prv = crt;
+            crt = readb(addr + len);
+            len++;
+        }
+
+        /* keep track of max. struct size */
+        if (max_len < len) {
+            max_len = len;
+            g_assert_cmpuint(max_len, <=, ep_table->max_structure_size);
+        }
+
+        /* start of next structure */
+        addr += len;
+    }
+
+    /* total table length and max struct size must match entry point values */
+    g_assert_cmpuint(ep_table->structure_table_length, ==,
+                     addr - ep_table->structure_table_address);
+    g_assert_cmpuint(ep_table->max_structure_size, ==, max_len);
+
+    /* required struct types must all be present */
+    for (i = 0; i < ARRAY_SIZE(required_struct_types); i++) {
+        g_assert(test_bit(required_struct_types[i], struct_bitmap));
+    }
+}
+
+static void test_acpi_one(const char *params, test_data *data)
+{
+    char *args;
+    uint8_t signature_low;
+    uint8_t signature_high;
+    uint16_t signature;
+    int i;
+    const char *device = "";
+
+    if (!g_strcmp0(data->machine, MACHINE_Q35)) {
+        device = ",id=hd -device ide-hd,drive=hd";
+    }
+
+    args = g_strdup_printf("-net none -display none %s -drive file=%s%s,",
+                           params ? params : "", disk, device);
+    qtest_start(args);
+
+   /* Wait at most 1 minute */
+#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
+#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
+
+    /* Poll until code has run and modified memory.  Once it has we know BIOS
+     * initialization is done.  TODO: check that IP reached the halt
+     * instruction.
+     */
+    for (i = 0; i < TEST_CYCLES; ++i) {
+        signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
+        signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
+        signature = (signature_high << 8) | signature_low;
+        if (signature == SIGNATURE) {
+            break;
+        }
+        g_usleep(TEST_DELAY);
+    }
+    g_assert_cmphex(signature, ==, SIGNATURE);
+
+    test_acpi_rsdp_address(data);
+    test_acpi_rsdp_table(data);
+    test_acpi_rsdt_table(data);
+    test_acpi_fadt_table(data);
+    test_acpi_facs_table(data);
+    test_acpi_dsdt_table(data);
+    test_acpi_tables(data);
+
+    if (iasl) {
+        if (getenv(ACPI_REBUILD_EXPECTED_AML)) {
+            dump_aml_files(data, true);
+        } else {
+            test_acpi_asl(data);
+        }
+    }
+
+    test_smbios_ep_address(data);
+    test_smbios_ep_table(data);
+    test_smbios_structs(data);
+
+    qtest_quit(global_qtest);
+    g_free(args);
+}
+
+static void test_acpi_tcg(void)
+{
+    test_data data;
+
+    /* Supplying -machine accel argument overrides the default (qtest).
+     * This is to make guest actually run.
+     */
+    memset(&data, 0, sizeof(data));
+    data.machine = MACHINE_PC;
+    test_acpi_one("-machine accel=tcg", &data);
+    free_test_data(&data);
+
+    memset(&data, 0, sizeof(data));
+    data.machine = MACHINE_Q35;
+    test_acpi_one("-machine q35,accel=tcg", &data);
+    free_test_data(&data);
+}
+
+int main(int argc, char *argv[])
+{
+    const char *arch = qtest_get_arch();
+    FILE *f = fopen(disk, "w");
+    int ret;
+    fwrite(boot_sector, 1, sizeof boot_sector, f);
+    fclose(f);
+
+    g_test_init(&argc, &argv, NULL);
+
+    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+        qtest_add_func("acpi/tcg", test_acpi_tcg);
+    }
+    ret = g_test_run();
+    unlink(disk);
+    return ret;
+}
index e4ad173d72732799f0b6eaf5cd4c604d249a3e30..2bef04c76f9556bd335ce6caacc8ff35aeb49844 100644 (file)
@@ -150,8 +150,10 @@ static void test_dynamic_globalprop(void)
     static GlobalProperty props[] = {
         { TYPE_DYNAMIC_PROPS, "prop1", "101" },
         { TYPE_DYNAMIC_PROPS, "prop2", "102" },
+        { TYPE_DYNAMIC_PROPS"-bad", "prop3", "103", true },
         {}
     };
+    int all_used;
 
     qdev_prop_register_global_list(props);
 
@@ -160,6 +162,8 @@ static void test_dynamic_globalprop(void)
 
     g_assert_cmpuint(mt->prop1, ==, 101);
     g_assert_cmpuint(mt->prop2, ==, 102);
+    all_used = qdev_prop_check_global();
+    g_assert_cmpuint(all_used, ==, 1);
 }
 
 int main(int argc, char **argv)
index de85f7610fbbf4cbdbee0bd5c96a88b571aa1aa4..8edb038bb3470a9f2d2af96f16bd3ee89dc6fc81 100644 (file)
@@ -277,31 +277,41 @@ static void curses_refresh(DisplayChangeListener *dcl)
              * events, we need to emit both for each key received */
             if (keycode & SHIFT) {
                 qemu_input_event_send_key_number(NULL, SHIFT_CODE, true);
+                qemu_input_event_send_key_delay(0);
             }
             if (keycode & CNTRL) {
                 qemu_input_event_send_key_number(NULL, CNTRL_CODE, true);
+                qemu_input_event_send_key_delay(0);
             }
             if (keycode & ALT) {
                 qemu_input_event_send_key_number(NULL, ALT_CODE, true);
+                qemu_input_event_send_key_delay(0);
             }
             if (keycode & ALTGR) {
                 qemu_input_event_send_key_number(NULL, GREY | ALT_CODE, true);
+                qemu_input_event_send_key_delay(0);
             }
 
             qemu_input_event_send_key_number(NULL, keycode & KEY_MASK, true);
+            qemu_input_event_send_key_delay(0);
             qemu_input_event_send_key_number(NULL, keycode & KEY_MASK, false);
+            qemu_input_event_send_key_delay(0);
 
             if (keycode & ALTGR) {
                 qemu_input_event_send_key_number(NULL, GREY | ALT_CODE, false);
+                qemu_input_event_send_key_delay(0);
             }
             if (keycode & ALT) {
                 qemu_input_event_send_key_number(NULL, ALT_CODE, false);
+                qemu_input_event_send_key_delay(0);
             }
             if (keycode & CNTRL) {
                 qemu_input_event_send_key_number(NULL, CNTRL_CODE, false);
+                qemu_input_event_send_key_delay(0);
             }
             if (keycode & SHIFT) {
                 qemu_input_event_send_key_number(NULL, SHIFT_CODE, false);
+                qemu_input_event_send_key_delay(0);
             }
         } else {
             keysym = curses2qemu[chr];
index 2a538607a2a443f17b58d366c820dfafea64423e..3025f50f4982beaf2273db1008cc42e5d4b00afe 100644 (file)
@@ -74,27 +74,6 @@ int index_from_key(const char *key)
     return i;
 }
 
-static KeyValue **keyvalues;
-static int keyvalues_size;
-static QEMUTimer *key_timer;
-
-static void free_keyvalues(void)
-{
-    g_free(keyvalues);
-    keyvalues = NULL;
-    keyvalues_size = 0;
-}
-
-static void release_keys(void *opaque)
-{
-    while (keyvalues_size > 0) {
-        qemu_input_event_send_key(NULL, keyvalues[--keyvalues_size],
-                                  false);
-    }
-
-    free_keyvalues();
-}
-
 static KeyValue *copy_key_value(KeyValue *src)
 {
     KeyValue *dst = g_new(KeyValue, 1);
@@ -107,30 +86,18 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
 {
     KeyValueList *p;
 
-    if (!key_timer) {
-        key_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, release_keys, NULL);
-    }
-
-    if (keyvalues != NULL) {
-        timer_del(key_timer);
-        release_keys(NULL);
-    }
-
     if (!has_hold_time) {
-        hold_time = 100;
+        hold_time = 0; /* use default */
     }
 
     for (p = keys; p != NULL; p = p->next) {
         qemu_input_event_send_key(NULL, copy_key_value(p->value), true);
-
-        keyvalues = g_realloc(keyvalues, sizeof(KeyValue *) *
-                              (keyvalues_size + 1));
-        keyvalues[keyvalues_size++] = copy_key_value(p->value);
+        qemu_input_event_send_key_delay(hold_time);
+    }
+    for (p = keys; p != NULL; p = p->next) {
+        qemu_input_event_send_key(NULL, copy_key_value(p->value), false);
+        qemu_input_event_send_key_delay(hold_time);
     }
-
-    /* delayed key up events */
-    timer_mod(key_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
-              muldiv64(get_ticks_per_sec(), hold_time, 1000));
 }
 
 static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
index 14c9434f5e9ffbdaeb57e4eeae154ad10ba441bc..89d9db78c029cbfc737e0d717021161031865b6a 100644 (file)
@@ -14,11 +14,31 @@ struct QemuInputHandlerState {
     QemuConsole       *con;
     QTAILQ_ENTRY(QemuInputHandlerState) node;
 };
+
+typedef struct QemuInputEventQueue QemuInputEventQueue;
+struct QemuInputEventQueue {
+    enum {
+        QEMU_INPUT_QUEUE_DELAY = 1,
+        QEMU_INPUT_QUEUE_EVENT,
+        QEMU_INPUT_QUEUE_SYNC,
+    } type;
+    QEMUTimer *timer;
+    uint32_t delay_ms;
+    QemuConsole *src;
+    InputEvent *evt;
+    QTAILQ_ENTRY(QemuInputEventQueue) node;
+};
+
 static QTAILQ_HEAD(, QemuInputHandlerState) handlers =
     QTAILQ_HEAD_INITIALIZER(handlers);
 static NotifierList mouse_mode_notifiers =
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
 
+static QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue) kbd_queue =
+    QTAILQ_HEAD_INITIALIZER(kbd_queue);
+static QEMUTimer *kbd_timer;
+static uint32_t kbd_default_delay_ms = 10;
+
 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
                                                    QemuInputHandler *handler)
 {
@@ -171,6 +191,73 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
     }
 }
 
+static void qemu_input_queue_process(void *opaque)
+{
+    struct QemuInputEventQueueHead *queue = opaque;
+    QemuInputEventQueue *item;
+
+    g_assert(!QTAILQ_EMPTY(queue));
+    item = QTAILQ_FIRST(queue);
+    g_assert(item->type == QEMU_INPUT_QUEUE_DELAY);
+    QTAILQ_REMOVE(queue, item, node);
+    g_free(item);
+
+    while (!QTAILQ_EMPTY(queue)) {
+        item = QTAILQ_FIRST(queue);
+        switch (item->type) {
+        case QEMU_INPUT_QUEUE_DELAY:
+            timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
+                      + item->delay_ms);
+            return;
+        case QEMU_INPUT_QUEUE_EVENT:
+            qemu_input_event_send(item->src, item->evt);
+            qapi_free_InputEvent(item->evt);
+            break;
+        case QEMU_INPUT_QUEUE_SYNC:
+            qemu_input_event_sync();
+            break;
+        }
+        QTAILQ_REMOVE(queue, item, node);
+        g_free(item);
+    }
+}
+
+static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue,
+                                   QEMUTimer *timer, uint32_t delay_ms)
+{
+    QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
+    bool start_timer = QTAILQ_EMPTY(queue);
+
+    item->type = QEMU_INPUT_QUEUE_DELAY;
+    item->delay_ms = delay_ms;
+    item->timer = timer;
+    QTAILQ_INSERT_TAIL(queue, item, node);
+
+    if (start_timer) {
+        timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
+                  + item->delay_ms);
+    }
+}
+
+static void qemu_input_queue_event(struct QemuInputEventQueueHead *queue,
+                                   QemuConsole *src, InputEvent *evt)
+{
+    QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
+
+    item->type = QEMU_INPUT_QUEUE_EVENT;
+    item->src = src;
+    item->evt = evt;
+    QTAILQ_INSERT_TAIL(queue, item, node);
+}
+
+static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
+{
+    QemuInputEventQueue *item = g_new0(QemuInputEventQueue, 1);
+
+    item->type = QEMU_INPUT_QUEUE_SYNC;
+    QTAILQ_INSERT_TAIL(queue, item, node);
+}
+
 void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
 {
     QemuInputHandlerState *s;
@@ -230,9 +317,14 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
 {
     InputEvent *evt;
     evt = qemu_input_event_new_key(key, down);
-    qemu_input_event_send(src, evt);
-    qemu_input_event_sync();
-    qapi_free_InputEvent(evt);
+    if (QTAILQ_EMPTY(&kbd_queue)) {
+        qemu_input_event_send(src, evt);
+        qemu_input_event_sync();
+        qapi_free_InputEvent(evt);
+    } else {
+        qemu_input_queue_event(&kbd_queue, src, evt);
+        qemu_input_queue_sync(&kbd_queue);
+    }
 }
 
 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
@@ -251,6 +343,16 @@ void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
     qemu_input_event_send_key(src, key, down);
 }
 
+void qemu_input_event_send_key_delay(uint32_t delay_ms)
+{
+    if (!kbd_timer) {
+        kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process,
+                                 &kbd_queue);
+    }
+    qemu_input_queue_delay(&kbd_queue, kbd_timer,
+                           delay_ms ? delay_ms : kbd_default_delay_ms);
+}
+
 InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
 {
     InputEvent *evt = g_new0(InputEvent, 1);
index 61b1f933bfaa2ae34661e22ae9bb632e93523f9f..1684206184a22c5d9e1f0a69542e78b78a7aad31 100644 (file)
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1553,7 +1553,9 @@ static void press_key(VncState *vs, int keysym)
 {
     int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
     qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
+    qemu_input_event_send_key_delay(0);
     qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
+    qemu_input_event_send_key_delay(0);
 }
 
 static int current_led_state(VncState *vs)
index 8ed6fec81472d8cb17662bc3958e5883bdebed8d..1ff8673acbd17e10715bf5b8ca749f8eda01c9d4 100644 (file)
@@ -21,6 +21,7 @@
 #include "disas/disas.h"
 #include "tcg.h"
 #include "qemu/bitops.h"
+#include "exec/cpu_ldst.h"
 
 #undef EAX
 #undef ECX
diff --git a/vl.c b/vl.c
index 0c15608bcbf4d6f93e7161fb7ece8e2a58c3569b..a3def97443124ad194f7c7b5cebaa331f74d1626 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -4541,6 +4541,8 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
+    qdev_prop_check_global();
+
     if (incoming) {
         Error *local_err = NULL;
         qemu_start_incoming_migration(incoming, &local_err);