aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/ssh.c10
-rw-r--r--cpus.c4
-rw-r--r--default-configs/pci.mak1
-rw-r--r--docs/specs/pci-testdev.txt26
-rw-r--r--hw/arm/armv7m.c12
-rw-r--r--hw/arm/boot.c4
-rw-r--r--hw/arm/musicpal.c8
-rw-r--r--hw/arm/nseries.c4
-rw-r--r--hw/arm/omap1.c12
-rw-r--r--hw/arm/realview.c22
-rw-r--r--hw/arm/versatilepb.c11
-rw-r--r--hw/audio/marvell_88w8618.c3
-rw-r--r--hw/block/fdc.c1
-rw-r--r--hw/block/m25p80.c1
-rw-r--r--hw/core/Makefile.objs1
-rw-r--r--hw/core/qdev-addr.c78
-rw-r--r--hw/display/pxa2xx_lcd.c2
-rw-r--r--hw/display/sm501.c3
-rw-r--r--hw/display/tcx.c1
-rw-r--r--hw/dma/pxa2xx_dma.c2
-rw-r--r--hw/dma/xilinx_axidma.c5
-rw-r--r--hw/gpio/zaurus.c2
-rw-r--r--hw/lm32/milkymist-hw.h1
-rw-r--r--hw/microblaze/boot.c2
-rw-r--r--hw/misc/Makefile.objs1
-rw-r--r--hw/misc/macio/mac_dbdma.c8
-rw-r--r--hw/misc/milkymist-pfpu.c4
-rw-r--r--hw/misc/pci-testdev.c325
-rw-r--r--hw/net/mcf_fec.c4
-rw-r--r--hw/net/milkymist-minimac2.c1
-rw-r--r--hw/pci-host/versatile.c399
-rw-r--r--hw/ppc/ppc405_boards.c2
-rw-r--r--hw/ppc/virtex_ml507.c2
-rw-r--r--hw/sparc/sun4m.c1
-rw-r--r--hw/virtio/virtio-balloon.c2
-rw-r--r--include/hw/pci/pci.h1
-rw-r--r--include/hw/qdev-addr.h10
-rw-r--r--include/hw/virtio/virtio.h2
-rw-r--r--include/qemu/bswap.h1
-rw-r--r--include/sysemu/kvm.h4
-rw-r--r--kvm-all.c133
-rw-r--r--kvm-stub.c10
-rw-r--r--linux-user/syscall.c12
-rwxr-xr-xscripts/kvm/vmxcap26
-rw-r--r--target-arm/cpu-qom.h4
-rw-r--r--target-arm/cpu.c1
-rw-r--r--target-arm/cpu.h2
-rw-r--r--target-arm/machine.c430
-rw-r--r--target-arm/translate.c1
-rw-r--r--target-i386/cpu.h1
-rw-r--r--target-i386/kvm.c13
-rw-r--r--target-i386/machine.c21
-rw-r--r--target-i386/translate.c1
-rw-r--r--ui/cocoa.m8
-rw-r--r--ui/input.c8
55 files changed, 1133 insertions, 521 deletions
diff --git a/block/ssh.c b/block/ssh.c
index 8f78e2e4b9..93a8b53ffd 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -109,7 +109,7 @@ static void ssh_state_free(BDRVSSHState *s)
/* Wrappers around error_report which make sure to dump as much
* information from libssh2 as possible.
*/
-static void
+static void GCC_FMT_ATTR(2, 3)
session_error_report(BDRVSSHState *s, const char *fs, ...)
{
va_list args;
@@ -132,7 +132,7 @@ session_error_report(BDRVSSHState *s, const char *fs, ...)
error_printf("\n");
}
-static void
+static void GCC_FMT_ATTR(2, 3)
sftp_error_report(BDRVSSHState *s, const char *fs, ...)
{
va_list args;
@@ -387,15 +387,13 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port,
}
/* host_key_check=md5:xx:yy:zz:... */
- if (strlen(host_key_check) >= 4 &&
- strncmp(host_key_check, "md5:", 4) == 0) {
+ if (strncmp(host_key_check, "md5:", 4) == 0) {
return check_host_key_hash(s, &host_key_check[4],
LIBSSH2_HOSTKEY_HASH_MD5, 16);
}
/* host_key_check=sha1:xx:yy:zz:... */
- if (strlen(host_key_check) >= 5 &&
- strncmp(host_key_check, "sha1:", 5) == 0) {
+ if (strncmp(host_key_check, "sha1:", 5) == 0) {
return check_host_key_hash(s, &host_key_check[5],
LIBSSH2_HOSTKEY_HASH_SHA1, 20);
}
diff --git a/cpus.c b/cpus.c
index c15ff6c5fe..5a98a370df 100644
--- a/cpus.c
+++ b/cpus.c
@@ -865,7 +865,7 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
CONTEXT tcgContext;
if (SuspendThread(cpu->hThread) == (DWORD)-1) {
- fprintf(stderr, "qemu:%s: GetLastError:%d\n", __func__,
+ fprintf(stderr, "qemu:%s: GetLastError:%lu\n", __func__,
GetLastError());
exit(1);
}
@@ -881,7 +881,7 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
cpu_signal(0);
if (ResumeThread(cpu->hThread) == (DWORD)-1) {
- fprintf(stderr, "qemu:%s: GetLastError:%d\n", __func__,
+ fprintf(stderr, "qemu:%s: GetLastError:%lu\n", __func__,
GetLastError());
exit(1);
}
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index bf2cad7df2..8a5b565dd9 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -25,3 +25,4 @@ CONFIG_SERIAL=y
CONFIG_SERIAL_PCI=y
CONFIG_IPACK=y
CONFIG_WDT_IB6300ESB=y
+CONFIG_PCI_TESTDEV=y
diff --git a/docs/specs/pci-testdev.txt b/docs/specs/pci-testdev.txt
new file mode 100644
index 0000000000..128ae222ef
--- /dev/null
+++ b/docs/specs/pci-testdev.txt
@@ -0,0 +1,26 @@
+pci-test is a device used for testing low level IO
+
+device implements up to two BARs: BAR0 and BAR1.
+Each BAR can be memory or IO. Guests must detect
+BAR type and act accordingly.
+
+Each BAR size is up to 4K bytes.
+Each BAR starts with the following header:
+
+typedef struct PCITestDevHdr {
+ uint8_t test; <- write-only, starts a given test number
+ uint8_t width_type; <- read-only, type and width of access for a given test.
+ 1,2,4 for byte,word or long write.
+ any other value if test not supported on this BAR
+ uint8_t pad0[2];
+ uint32_t offset; <- read-only, offset in this BAR for a given test
+ uint32_t data; <- read-only, data to use for a given test
+ uint32_t count; <- for debugging. number of writes detected.
+ uint8_t name[]; <- for debugging. 0-terminated ASCII string.
+} PCITestDevHdr;
+
+All registers are little endian.
+
+device is expected to always implement tests 0 to N on each BAR, and to add new
+tests with higher numbers. In this way a guest can scan test numbers until it
+detects an access type that it does not support on this BAR, then stop.
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 2ae3576760..93422bc7be 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -56,7 +56,7 @@ static uint32_t bitband_readw(void *opaque, hwaddr offset)
addr = bitband_addr(opaque, offset) & ~1;
mask = (1 << ((offset >> 2) & 15));
mask = tswap16(mask);
- cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
+ cpu_physical_memory_read(addr, &v, 2);
return (v & mask) != 0;
}
@@ -69,12 +69,12 @@ static void bitband_writew(void *opaque, hwaddr offset,
addr = bitband_addr(opaque, offset) & ~1;
mask = (1 << ((offset >> 2) & 15));
mask = tswap16(mask);
- cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
+ cpu_physical_memory_read(addr, &v, 2);
if (value & 1)
v |= mask;
else
v &= ~mask;
- cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
+ cpu_physical_memory_write(addr, &v, 2);
}
static uint32_t bitband_readl(void *opaque, hwaddr offset)
@@ -85,7 +85,7 @@ static uint32_t bitband_readl(void *opaque, hwaddr offset)
addr = bitband_addr(opaque, offset) & ~3;
mask = (1 << ((offset >> 2) & 31));
mask = tswap32(mask);
- cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
+ cpu_physical_memory_read(addr, &v, 4);
return (v & mask) != 0;
}
@@ -98,12 +98,12 @@ static void bitband_writel(void *opaque, hwaddr offset,
addr = bitband_addr(opaque, offset) & ~3;
mask = (1 << ((offset >> 2) & 31));
mask = tswap32(mask);
- cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
+ cpu_physical_memory_read(addr, &v, 4);
if (value & 1)
v |= mask;
else
v &= ~mask;
- cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
+ cpu_physical_memory_write(addr, &v, 4);
}
static const MemoryRegionOps bitband_ops = {
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index e9c09454ac..f451529fce 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -128,7 +128,7 @@ static void set_kernel_args(const struct arm_boot_info *info)
int cmdline_size;
cmdline_size = strlen(info->kernel_cmdline);
- cpu_physical_memory_write(p + 8, (void *)info->kernel_cmdline,
+ cpu_physical_memory_write(p + 8, info->kernel_cmdline,
cmdline_size + 1);
cmdline_size = (cmdline_size >> 2) + 1;
WRITE_WORD(p, cmdline_size + 2);
@@ -219,7 +219,7 @@ static void set_kernel_args_old(const struct arm_boot_info *info)
}
s = info->kernel_cmdline;
if (s) {
- cpu_physical_memory_write(p, (void *)s, strlen(s) + 1);
+ cpu_physical_memory_write(p, s, strlen(s) + 1);
} else {
WRITE_WORD(p, 0);
}
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 31586c652e..f33ba9a039 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -170,12 +170,12 @@ static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc)
cpu_to_le16s(&desc->buffer_size);
cpu_to_le32s(&desc->buffer);
cpu_to_le32s(&desc->next);
- cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
+ cpu_physical_memory_write(addr, desc, sizeof(*desc));
}
static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
{
- cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
+ cpu_physical_memory_read(addr, desc, sizeof(*desc));
le32_to_cpus(&desc->cmdstat);
le16_to_cpus(&desc->bytes);
le16_to_cpus(&desc->buffer_size);
@@ -229,12 +229,12 @@ static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc)
cpu_to_le16s(&desc->bytes);
cpu_to_le32s(&desc->buffer);
cpu_to_le32s(&desc->next);
- cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
+ cpu_physical_memory_write(addr, desc, sizeof(*desc));
}
static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc)
{
- cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
+ cpu_physical_memory_read(addr, desc, sizeof(*desc));
le32_to_cpus(&desc->cmdstat);
le16_to_cpus(&desc->res);
le16_to_cpus(&desc->bytes);
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index 4976438ae6..f6c9dc09ef 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -970,7 +970,7 @@ static void n800_gpmc_init(struct n800_s *s)
(4 << 0); /* BASEADDRESS */
cpu_physical_memory_write(0x6800a078, /* GPMC_CONFIG7_0 */
- (void *) &config7, sizeof(config7));
+ &config7, sizeof(config7));
}
/* Setup sequence done by the bootloader */
@@ -982,7 +982,7 @@ static void n8x0_boot_init(void *opaque)
/* PRCM setup */
#define omap_writel(addr, val) \
buf = (val); \
- cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
+ cpu_physical_memory_write(addr, &buf, sizeof(buf))
omap_writel(0x48008060, 0x41); /* PRCM_CLKSRC_CTRL */
omap_writel(0x48008070, 1); /* PRCM_CLKOUT_CTRL */
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index f59f0f291a..c06c642acc 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -31,7 +31,7 @@ uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
uint8_t ret;
OMAP_8B_REG(addr);
- cpu_physical_memory_read(addr, (void *) &ret, 1);
+ cpu_physical_memory_read(addr, &ret, 1);
return ret;
}
@@ -41,7 +41,7 @@ void omap_badwidth_write8(void *opaque, hwaddr addr,
uint8_t val8 = value;
OMAP_8B_REG(addr);
- cpu_physical_memory_write(addr, (void *) &val8, 1);
+ cpu_physical_memory_write(addr, &val8, 1);
}
uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
@@ -49,7 +49,7 @@ uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
uint16_t ret;
OMAP_16B_REG(addr);
- cpu_physical_memory_read(addr, (void *) &ret, 2);
+ cpu_physical_memory_read(addr, &ret, 2);
return ret;
}
@@ -59,7 +59,7 @@ void omap_badwidth_write16(void *opaque, hwaddr addr,
uint16_t val16 = value;
OMAP_16B_REG(addr);
- cpu_physical_memory_write(addr, (void *) &val16, 2);
+ cpu_physical_memory_write(addr, &val16, 2);
}
uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
@@ -67,7 +67,7 @@ uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
uint32_t ret;
OMAP_32B_REG(addr);
- cpu_physical_memory_read(addr, (void *) &ret, 4);
+ cpu_physical_memory_read(addr, &ret, 4);
return ret;
}
@@ -75,7 +75,7 @@ void omap_badwidth_write32(void *opaque, hwaddr addr,
uint32_t value)
{
OMAP_32B_REG(addr);
- cpu_physical_memory_write(addr, (void *) &value, 4);
+ cpu_physical_memory_write(addr, &value, 4);
}
/* MPU OS timers */
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index feabfc58d4..d6f47bf4d4 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -217,9 +217,13 @@ static void realview_init(QEMUMachineInitArgs *args,
dev = qdev_create(NULL, "realview_pci");
busdev = SYS_BUS_DEVICE(dev);
qdev_init_nofail(dev);
- sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */
- sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */
- sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */
+ sysbus_mmio_map(busdev, 0, 0x10019000); /* PCI controller registers */
+ sysbus_mmio_map(busdev, 1, 0x60000000); /* PCI self-config */
+ sysbus_mmio_map(busdev, 2, 0x61000000); /* PCI config */
+ sysbus_mmio_map(busdev, 3, 0x62000000); /* PCI I/O */
+ sysbus_mmio_map(busdev, 4, 0x63000000); /* PCI memory window 1 */
+ sysbus_mmio_map(busdev, 5, 0x64000000); /* PCI memory window 2 */
+ sysbus_mmio_map(busdev, 6, 0x68000000); /* PCI memory window 3 */
sysbus_connect_irq(busdev, 0, pic[48]);
sysbus_connect_irq(busdev, 1, pic[49]);
sysbus_connect_irq(busdev, 2, pic[50]);
@@ -303,12 +307,12 @@ static void realview_init(QEMUMachineInitArgs *args,
/* 0x58000000 PISMO. */
/* 0x5c000000 PISMO. */
/* 0x60000000 PCI. */
- /* 0x61000000 PCI Self Config. */
- /* 0x62000000 PCI Config. */
- /* 0x63000000 PCI IO. */
- /* 0x64000000 PCI mem 0. */
- /* 0x68000000 PCI mem 1. */
- /* 0x6c000000 PCI mem 2. */
+ /* 0x60000000 PCI Self Config. */
+ /* 0x61000000 PCI Config. */
+ /* 0x62000000 PCI IO. */
+ /* 0x63000000 PCI mem 0. */
+ /* 0x64000000 PCI mem 1. */
+ /* 0x68000000 PCI mem 2. */
/* ??? Hack to map an additional page of ram for the secondary CPU
startup code. I guess this works on real hardware because the
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 25c665ab27..753757ea19 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -224,16 +224,19 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
dev = qdev_create(NULL, "versatile_pci");
busdev = SYS_BUS_DEVICE(dev);
qdev_init_nofail(dev);
- sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */
- sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */
+ sysbus_mmio_map(busdev, 0, 0x10001000); /* PCI controller regs */
+ sysbus_mmio_map(busdev, 1, 0x41000000); /* PCI self-config */
+ sysbus_mmio_map(busdev, 2, 0x42000000); /* PCI config */
+ sysbus_mmio_map(busdev, 3, 0x43000000); /* PCI I/O */
+ sysbus_mmio_map(busdev, 4, 0x44000000); /* PCI memory window 1 */
+ sysbus_mmio_map(busdev, 5, 0x50000000); /* PCI memory window 2 */
+ sysbus_mmio_map(busdev, 6, 0x60000000); /* PCI memory window 3 */
sysbus_connect_irq(busdev, 0, sic[27]);
sysbus_connect_irq(busdev, 1, sic[28]);
sysbus_connect_irq(busdev, 2, sic[29]);
sysbus_connect_irq(busdev, 3, sic[30]);
pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
- /* The Versatile PCI bridge does not provide access to PCI IO space,
- so many of the qemu PCI devices are not useable. */
for(n = 0; n < nb_nics; n++) {
nd = &nd_table[n];
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index f9b68fd311..de06dfd7d2 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -77,8 +77,7 @@ static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
if (block_size > 4096) {
return;
}
- cpu_physical_memory_read(s->target_buffer + s->play_pos, (void *)buf,
- block_size);
+ cpu_physical_memory_read(s->target_buffer + s->play_pos, buf, block_size);
mem_buffer = buf;
if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
if (s->playback_mode & MP_AUDIO_MONO) {
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 1ed874f074..f1f1fd7f3b 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -33,7 +33,6 @@
#include "qemu/timer.h"
#include "hw/isa/isa.h"
#include "hw/sysbus.h"
-#include "hw/qdev-addr.h"
#include "sysemu/blockdev.h"
#include "sysemu/sysemu.h"
#include "qemu/log.h"
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index efcc7f4c83..b3ca19ae52 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -24,7 +24,6 @@
#include "hw/hw.h"
#include "sysemu/blockdev.h"
#include "hw/ssi.h"
-#include "hw/devices.h"
#ifndef M25P80_ERR_DEBUG
#define M25P80_ERR_DEBUG 0
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index 94109f32e2..950146c6ff 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -9,6 +9,5 @@ common-obj-$(CONFIG_PTIMER) += ptimer.o
common-obj-$(CONFIG_SOFTMMU) += sysbus.o
common-obj-$(CONFIG_SOFTMMU) += null-machine.o
common-obj-$(CONFIG_SOFTMMU) += loader.o
-common-obj-$(CONFIG_SOFTMMU) += qdev-addr.o
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
diff --git a/hw/core/qdev-addr.c b/hw/core/qdev-addr.c
deleted file mode 100644
index 80a38bb017..0000000000
--- a/hw/core/qdev-addr.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "hw/qdev.h"
-#include "hw/qdev-addr.h"
-#include "exec/hwaddr.h"
-#include "qapi/qmp/qerror.h"
-#include "qapi/visitor.h"
-
-/* --- target physical address --- */
-
-static int parse_taddr(DeviceState *dev, Property *prop, const char *str)
-{
- hwaddr *ptr = qdev_get_prop_ptr(dev, prop);
-
- *ptr = strtoull(str, NULL, 16);
- return 0;
-}
-
-static int print_taddr(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- hwaddr *ptr = qdev_get_prop_ptr(dev, prop);
- return snprintf(dest, len, "0x" TARGET_FMT_plx, *ptr);
-}
-
-static void get_taddr(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- hwaddr *ptr = qdev_get_prop_ptr(dev, prop);
- int64_t value;
-
- value = *ptr;
- visit_type_int64(v, &value, name, errp);
-}
-
-static void set_taddr(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- hwaddr *ptr = qdev_get_prop_ptr(dev, prop);
- Error *local_err = NULL;
- int64_t value;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- visit_type_int64(v, &value, name, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if ((uint64_t)value <= (uint64_t) ~(hwaddr)0) {
- *ptr = value;
- } else {
- error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
- dev->id?:"", name, value, (uint64_t) 0,
- (uint64_t) ~(hwaddr)0);
- }
-}
-
-
-PropertyInfo qdev_prop_taddr = {
- .name = "taddr",
- .parse = parse_taddr,
- .print = print_taddr,
- .get = get_taddr,
- .set = set_taddr,
-};
-
-void qdev_prop_set_taddr(DeviceState *dev, const char *name, hwaddr value)
-{
- Error *errp = NULL;
- object_property_set_int(OBJECT(dev), value, name, &errp);
- assert(!errp);
-
-}
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
index 12d9cd2808..76276cf7f1 100644
--- a/hw/display/pxa2xx_lcd.c
+++ b/hw/display/pxa2xx_lcd.c
@@ -315,7 +315,7 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
continue;
}
- cpu_physical_memory_read(descptr, (void *)&desc, sizeof(desc));
+ cpu_physical_memory_read(descptr, &desc, sizeof(desc));
s->dma_ch[i].descriptor = tswap32(desc.fdaddr);
s->dma_ch[i].source = tswap32(desc.fsaddr);
s->dma_ch[i].id = tswap32(desc.fidr);
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index f0e6d7022f..916816fc24 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -28,7 +28,6 @@
#include "ui/console.h"
#include "hw/devices.h"
#include "hw/sysbus.h"
-#include "hw/qdev-addr.h"
#include "qemu/range.h"
#include "ui/pixel_ops.h"
@@ -1434,7 +1433,7 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
/* bridge to usb host emulation module */
dev = qdev_create(NULL, "sysbus-ohci");
qdev_prop_set_uint32(dev, "num-ports", 2);
- qdev_prop_set_taddr(dev, "dma-offset", base);
+ qdev_prop_set_uint64(dev, "dma-offset", base);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0,
base + MMIO_BASE_OFFSET + SM501_USB_HOST);
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 77c7191c76..d7465c63f1 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -26,7 +26,6 @@
#include "ui/console.h"
#include "ui/pixel_ops.h"
#include "hw/sysbus.h"
-#include "hw/qdev-addr.h"
#define MAXX 1024
#define MAXY 768
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index 6e4c1f6d62..b60569fd88 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -151,7 +151,7 @@ static inline void pxa2xx_dma_descriptor_fetch(
if ((s->chan[ch].descr & DDADR_BREN) && (s->chan[ch].state & DCSR_CMPST))
daddr += 32;
- cpu_physical_memory_read(daddr, (uint8_t *) desc, 16);
+ cpu_physical_memory_read(daddr, desc, 16);
s->chan[ch].descr = desc[DDADR];
s->chan[ch].src = desc[DSADR];
s->chan[ch].dest = desc[DTADR];
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index 1c23762210..3a3ef8aff3 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -26,7 +26,6 @@
#include "qemu/timer.h"
#include "hw/ptimer.h"
#include "qemu/log.h"
-#include "hw/qdev-addr.h"
#include "qapi/qmp/qerror.h"
#include "hw/stream.h"
@@ -197,7 +196,7 @@ static void stream_desc_load(struct Stream *s, hwaddr addr)
{
struct SDesc *d = &s->desc;
- cpu_physical_memory_read(addr, (void *) d, sizeof *d);
+ cpu_physical_memory_read(addr, d, sizeof *d);
/* Convert from LE into host endianness. */
d->buffer_address = le64_to_cpu(d->buffer_address);
@@ -215,7 +214,7 @@ static void stream_desc_store(struct Stream *s, hwaddr addr)
d->nxtdesc = cpu_to_le64(d->nxtdesc);
d->control = cpu_to_le32(d->control);
d->status = cpu_to_le32(d->status);
- cpu_physical_memory_write(addr, (void *) d, sizeof *d);
+ cpu_physical_memory_write(addr, d, sizeof *d);
}
static void stream_update_irq(struct Stream *s)
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index d853ea1310..c6cdef3212 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -287,6 +287,6 @@ static struct QEMU_PACKED sl_param_info {
void sl_bootparam_write(hwaddr ptr)
{
- cpu_physical_memory_write(ptr, (void *)&zaurus_bootparam,
+ cpu_physical_memory_write(ptr, &zaurus_bootparam,
sizeof(struct sl_param_info));
}
diff --git a/hw/lm32/milkymist-hw.h b/hw/lm32/milkymist-hw.h
index 4e86c4e832..5317ce6e2d 100644
--- a/hw/lm32/milkymist-hw.h
+++ b/hw/lm32/milkymist-hw.h
@@ -2,7 +2,6 @@
#define QEMU_HW_MILKYMIST_H
#include "hw/qdev.h"
-#include "hw/qdev-addr.h"
#include "net/net.h"
static inline DeviceState *milkymist_uart_create(hwaddr base,
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 23cb11d70e..e543d886b8 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -80,7 +80,7 @@ static int microblaze_load_dtb(hwaddr addr,
}
}
- cpu_physical_memory_write(addr, (void *)fdt, fdt_size);
+ cpu_physical_memory_write(addr, fdt, fdt_size);
#else
/* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
to the kernel. */
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 03699c3365..11b18a4196 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -4,6 +4,7 @@ common-obj-$(CONFIG_TMP105) += tmp105.o
common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o
common-obj-$(CONFIG_SGA) += sga.o
common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
+common-obj-$(CONFIG_PCI_TESTDEV) += pci-testdev.o
obj-$(CONFIG_VMPORT) += vmport.o
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index a2363bbdf2..2fc7f87bb6 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -192,7 +192,7 @@ static void dbdma_cmdptr_load(DBDMA_channel *ch)
DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
ch->regs[DBDMA_CMDPTR_LO]);
cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
- (uint8_t*)&ch->current, sizeof(dbdma_cmd));
+ &ch->current, sizeof(dbdma_cmd));
}
static void dbdma_cmdptr_save(DBDMA_channel *ch)
@@ -203,7 +203,7 @@ static void dbdma_cmdptr_save(DBDMA_channel *ch)
le16_to_cpu(ch->current.xfer_status),
le16_to_cpu(ch->current.res_count));
cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
- (uint8_t*)&ch->current, sizeof(dbdma_cmd));
+ &ch->current, sizeof(dbdma_cmd));
}
static void kill_channel(DBDMA_channel *ch)
@@ -454,7 +454,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
return;
}
- cpu_physical_memory_read(addr, (uint8_t*)&val, len);
+ cpu_physical_memory_read(addr, &val, len);
if (len == 2)
val = (val << 16) | (current->cmd_dep & 0x0000ffff);
@@ -499,7 +499,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
else if (len == 1)
val >>= 24;
- cpu_physical_memory_write(addr, (uint8_t*)&val, len);
+ cpu_physical_memory_write(addr, &val, len);
if (conditional_wait(ch))
goto wait;
diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c
index ad44b4db22..fe1b039550 100644
--- a/hw/misc/milkymist-pfpu.c
+++ b/hw/misc/milkymist-pfpu.c
@@ -228,8 +228,8 @@ static int pfpu_decode_insn(MilkymistPFPUState *s)
hwaddr dma_ptr =
get_dma_address(s->regs[R_MESHBASE],
s->gp_regs[GPR_X], s->gp_regs[GPR_Y]);
- cpu_physical_memory_write(dma_ptr, (uint8_t *)&a, 4);
- cpu_physical_memory_write(dma_ptr + 4, (uint8_t *)&b, 4);
+ cpu_physical_memory_write(dma_ptr, &a, 4);
+ cpu_physical_memory_write(dma_ptr + 4, &b, 4);
s->regs[R_LASTDMA] = dma_ptr + 4;
D_EXEC(qemu_log("VECTOUT a=%08x b=%08x dma=%08x\n", a, b, dma_ptr));
trace_milkymist_pfpu_vectout(a, b, dma_ptr);
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
new file mode 100644
index 0000000000..71ce5a3e08
--- /dev/null
+++ b/hw/misc/pci-testdev.c
@@ -0,0 +1,325 @@
+/*
+ * QEMU PCI test device
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "qemu/event_notifier.h"
+#include "qemu/osdep.h"
+
+typedef struct PCITestDevHdr {
+ uint8_t test;
+ uint8_t width;
+ uint8_t pad0[2];
+ uint32_t offset;
+ uint8_t data;
+ uint8_t pad1[3];
+ uint32_t count;
+ uint8_t name[];
+} PCITestDevHdr;
+
+typedef struct IOTest {
+ MemoryRegion *mr;
+ EventNotifier notifier;
+ bool hasnotifier;
+ unsigned size;
+ bool match_data;
+ PCITestDevHdr *hdr;
+ unsigned bufsize;
+} IOTest;
+
+#define IOTEST_DATAMATCH 0xFA
+#define IOTEST_NOMATCH 0xCE
+
+#define IOTEST_IOSIZE 128
+#define IOTEST_MEMSIZE 2048
+
+static const char *iotest_test[] = {
+ "no-eventfd",
+ "wildcard-eventfd",
+ "datamatch-eventfd"
+};
+
+static const char *iotest_type[] = {
+ "mmio",
+ "portio"
+};
+
+#define IOTEST_TEST(i) (iotest_test[((i) % ARRAY_SIZE(iotest_test))])
+#define IOTEST_TYPE(i) (iotest_type[((i) / ARRAY_SIZE(iotest_test))])
+#define IOTEST_MAX_TEST (ARRAY_SIZE(iotest_test))
+#define IOTEST_MAX_TYPE (ARRAY_SIZE(iotest_type))
+#define IOTEST_MAX (IOTEST_MAX_TEST * IOTEST_MAX_TYPE)
+
+enum {
+ IOTEST_ACCESS_NAME,
+ IOTEST_ACCESS_DATA,
+ IOTEST_ACCESS_MAX,
+};
+
+#define IOTEST_ACCESS_TYPE uint8_t
+#define IOTEST_ACCESS_WIDTH (sizeof(uint8_t))
+
+typedef struct PCITestDevState {
+ PCIDevice dev;
+ MemoryRegion mmio;
+ MemoryRegion portio;
+ IOTest *tests;
+ int current;
+} PCITestDevState;
+
+#define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio"))
+#define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ? &(d)->mmio : &(d)->portio)
+#define IOTEST_SIZE(i) (IOTEST_IS_MEM(i) ? IOTEST_MEMSIZE : IOTEST_IOSIZE)
+#define IOTEST_PCI_BAR(i) (IOTEST_IS_MEM(i) ? PCI_BASE_ADDRESS_SPACE_MEMORY : \
+ PCI_BASE_ADDRESS_SPACE_IO)
+
+static int pci_testdev_start(IOTest *test)
+{
+ test->hdr->count = 0;
+ if (!test->hasnotifier) {
+ return 0;
+ }
+ event_notifier_test_and_clear(&test->notifier);
+ memory_region_add_eventfd(test->mr,
+ le32_to_cpu(test->hdr->offset),
+ test->size,
+ test->match_data,
+ test->hdr->data,
+ &test->notifier);
+ return 0;
+}
+
+static void pci_testdev_stop(IOTest *test)
+{
+ if (!test->hasnotifier) {
+ return;
+ }
+ memory_region_del_eventfd(test->mr,
+ le32_to_cpu(test->hdr->offset),
+ test->size,
+ test->match_data,
+ test->hdr->data,
+ &test->notifier);
+}
+
+static void
+pci_testdev_reset(PCITestDevState *d)
+{
+ if (d->current == -1) {
+ return;
+ }
+ pci_testdev_stop(&d->tests[d->current]);
+ d->current = -1;
+}
+
+static void pci_testdev_inc(IOTest *test, unsigned inc)
+{
+ uint32_t c = le32_to_cpu(test->hdr->count);
+ test->hdr->count = cpu_to_le32(c + inc);
+}
+
+static void
+pci_testdev_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, int type)
+{
+ PCITestDevState *d = opaque;
+ IOTest *test;
+ int t, r;
+
+ if (addr == offsetof(PCITestDevHdr, test)) {
+ pci_testdev_reset(d);
+ if (val >= IOTEST_MAX_TEST) {
+ return;
+ }
+ t = type * IOTEST_MAX_TEST + val;
+ r = pci_testdev_start(&d->tests[t]);
+ if (r < 0) {
+ return;
+ }
+ d->current = t;
+ return;
+ }
+ if (d->current < 0) {
+ return;
+ }
+ test = &d->tests[d->current];
+ if (addr != le32_to_cpu(test->hdr->offset)) {
+ return;
+ }
+ if (test->match_data && test->size != size) {
+ return;
+ }
+ if (test->match_data && val != test->hdr->data) {
+ return;
+ }
+ pci_testdev_inc(test, 1);
+}
+
+static uint64_t
+pci_testdev_read(void *opaque, hwaddr addr, unsigned size)
+{
+ PCITestDevState *d = opaque;
+ const char *buf;
+ IOTest *test;
+ if (d->current < 0) {
+ return 0;
+ }
+ test = &d->tests[d->current];
+ buf = (const char *)test->hdr;
+ if (addr + size >= test->bufsize) {
+ return 0;
+ }
+ if (test->hasnotifier) {
+ event_notifier_test_and_clear(&test->notifier);
+ }
+ return buf[addr];
+}
+
+static void
+pci_testdev_mmio_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ pci_testdev_write(opaque, addr, val, size, 0);
+}
+
+static void
+pci_testdev_pio_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ pci_testdev_write(opaque, addr, val, size, 1);
+}
+
+static const MemoryRegionOps pci_testdev_mmio_ops = {
+ .read = pci_testdev_read,
+ .write = pci_testdev_mmio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static const MemoryRegionOps pci_testdev_pio_ops = {
+ .read = pci_testdev_read,
+ .write = pci_testdev_pio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static int pci_testdev_init(PCIDevice *pci_dev)
+{
+ PCITestDevState *d = DO_UPCAST(PCITestDevState, dev, pci_dev);
+ uint8_t *pci_conf;
+ char *name;
+ int r, i;
+
+ pci_conf = d->dev.config;
+
+ pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */
+
+ memory_region_init_io(&d->mmio, &pci_testdev_mmio_ops, d,
+ "pci-testdev-mmio", IOTEST_MEMSIZE * 2);
+ memory_region_init_io(&d->portio, &pci_testdev_pio_ops, d,
+ "pci-testdev-portio", IOTEST_IOSIZE * 2);
+ pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+ pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio);
+
+ d->current = -1;
+ d->tests = g_malloc0(IOTEST_MAX * sizeof *d->tests);
+ for (i = 0; i < IOTEST_MAX; ++i) {
+ IOTest *test = &d->tests[i];
+ name = g_strdup_printf("%s-%s", IOTEST_TYPE(i), IOTEST_TEST(i));
+ test->bufsize = sizeof(PCITestDevHdr) + strlen(name) + 1;
+ test->hdr = g_malloc0(test->bufsize);
+ memcpy(test->hdr->name, name, strlen(name) + 1);
+ g_free(name);
+ test->hdr->offset = cpu_to_le32(IOTEST_SIZE(i) + i * IOTEST_ACCESS_WIDTH);
+ test->size = IOTEST_ACCESS_WIDTH;
+ test->match_data = strcmp(IOTEST_TEST(i), "wildcard-eventfd");
+ test->hdr->test = i;
+ test->hdr->data = test->match_data ? IOTEST_DATAMATCH : IOTEST_NOMATCH;
+ test->hdr->width = IOTEST_ACCESS_WIDTH;
+ test->mr = IOTEST_REGION(d, i);
+ if (!strcmp(IOTEST_TEST(i), "no-eventfd")) {
+ test->hasnotifier = false;
+ continue;
+ }
+ r = event_notifier_init(&test->notifier, 0);
+ assert(r >= 0);
+ test->hasnotifier = true;
+ }
+
+ return 0;
+}
+
+static void
+pci_testdev_uninit(PCIDevice *dev)
+{
+ PCITestDevState *d = DO_UPCAST(PCITestDevState, dev, dev);
+ int i;
+
+ pci_testdev_reset(d);
+ for (i = 0; i < IOTEST_MAX; ++i) {
+ if (d->tests[i].hasnotifier) {
+ event_notifier_cleanup(&d->tests[i].notifier);
+ }
+ g_free(d->tests[i].hdr);
+ }
+ g_free(d->tests);
+ memory_region_destroy(&d->mmio);
+ memory_region_destroy(&d->portio);
+}
+
+static void qdev_pci_testdev_reset(DeviceState *dev)
+{
+ PCITestDevState *d = DO_UPCAST(PCITestDevState, dev.qdev, dev);
+ pci_testdev_reset(d);
+}
+
+static void pci_testdev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_testdev_init;
+ k->exit = pci_testdev_uninit;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT;
+ k->device_id = PCI_DEVICE_ID_REDHAT_TEST;
+ k->revision = 0x00;
+ k->class_id = PCI_CLASS_OTHERS;
+ dc->desc = "PCI Test Device";
+ dc->reset = qdev_pci_testdev_reset;
+}
+
+static const TypeInfo pci_testdev_info = {
+ .name = "pci-testdev",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCITestDevState),
+ .class_init = pci_testdev_class_init,
+};
+
+static void pci_testdev_register_types(void)
+{
+ type_register_static(&pci_testdev_info);
+}
+
+type_init(pci_testdev_register_types)
diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
index 9b6805267d..2ef5a0d73d 100644
--- a/hw/net/mcf_fec.c
+++ b/hw/net/mcf_fec.c
@@ -108,7 +108,7 @@ typedef struct {
static void mcf_fec_read_bd(mcf_fec_bd *bd, uint32_t addr)
{
- cpu_physical_memory_read(addr, (uint8_t *)bd, sizeof(*bd));
+ cpu_physical_memory_read(addr, bd, sizeof(*bd));
be16_to_cpus(&bd->flags);
be16_to_cpus(&bd->length);
be32_to_cpus(&bd->data);
@@ -120,7 +120,7 @@ static void mcf_fec_write_bd(mcf_fec_bd *bd, uint32_t addr)
tmp.flags = cpu_to_be16(bd->flags);
tmp.length = cpu_to_be16(bd->length);
tmp.data = cpu_to_be32(bd->data);
- cpu_physical_memory_write(addr, (uint8_t *)&tmp, sizeof(tmp));
+ cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
}
static void mcf_fec_update(mcf_fec_state *s)
diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c
index 29618e8efa..4ef6318418 100644
--- a/hw/net/milkymist-minimac2.c
+++ b/hw/net/milkymist-minimac2.c
@@ -27,7 +27,6 @@
#include "trace.h"
#include "net/net.h"
#include "qemu/error-report.h"
-#include "hw/qdev-addr.h"
#include <zlib.h>
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
index d67ca796fb..540daf75cc 100644
--- a/hw/pci-host/versatile.c
+++ b/hw/pci-host/versatile.c
@@ -9,34 +9,235 @@
#include "hw/sysbus.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_host.h"
#include "exec/address-spaces.h"
+/* Old and buggy versions of QEMU used the wrong mapping from
+ * PCI IRQs to system interrupt lines. Unfortunately the Linux
+ * kernel also had the corresponding bug in setting up interrupts
+ * (so older kernels work on QEMU and not on real hardware).
+ * We automatically detect these broken kernels and flip back
+ * to the broken irq mapping by spotting guest writes to the
+ * PCI_INTERRUPT_LINE register to see where the guest thinks
+ * interrupts are going to be routed. So we start in state
+ * ASSUME_OK on reset, and transition to either BROKEN or
+ * FORCE_OK at the first write to an INTERRUPT_LINE register for
+ * a slot where broken and correct interrupt mapping would differ.
+ * Once in either BROKEN or FORCE_OK we never transition again;
+ * this allows a newer kernel to use the INTERRUPT_LINE
+ * registers arbitrarily once it has indicated that it isn't
+ * broken in its init code somewhere.
+ */
+enum {
+ PCI_VPB_IRQMAP_ASSUME_OK,
+ PCI_VPB_IRQMAP_BROKEN,
+ PCI_VPB_IRQMAP_FORCE_OK,
+};
+
typedef struct {
- SysBusDevice busdev;
+ PCIHostState parent_obj;
+
qemu_irq irq[4];
- int realview;
+ MemoryRegion controlregs;
MemoryRegion mem_config;
MemoryRegion mem_config2;
- MemoryRegion isa;
+ /* Containers representing the PCI address spaces */
+ MemoryRegion pci_io_space;
+ MemoryRegion pci_mem_space;
+ /* Alias regions into PCI address spaces which we expose as sysbus regions.
+ * The offsets into pci_mem_space are controlled by the imap registers.
+ */
+ MemoryRegion pci_io_window;
+ MemoryRegion pci_mem_window[3];
+ PCIBus pci_bus;
+ PCIDevice pci_dev;
+
+ /* Constant for life of device: */
+ int realview;
+ uint32_t mem_win_size[3];
+
+ /* Variable state: */
+ uint32_t imap[3];
+ uint32_t smap[3];
+ uint32_t selfid;
+ uint32_t flags;
+ uint8_t irq_mapping;
} PCIVPBState;
-static inline uint32_t vpb_pci_config_addr(hwaddr addr)
+static void pci_vpb_update_window(PCIVPBState *s, int i)
+{
+ /* Adjust the offset of the alias region we use for
+ * the memory window i to account for a change in the
+ * value of the corresponding IMAP register.
+ * Note that the semantics of the IMAP register differ
+ * for realview and versatile variants of the controller.
+ */
+ hwaddr offset;
+ if (s->realview) {
+ /* Top bits of register (masked according to window size) provide
+ * top bits of PCI address.
+ */
+ offset = s->imap[i] & ~(s->mem_win_size[i] - 1);
+ } else {
+ /* Bottom 4 bits of register provide top 4 bits of PCI address */
+ offset = s->imap[i] << 28;
+ }
+ memory_region_set_alias_offset(&s->pci_mem_window[i], offset);
+}
+
+static void pci_vpb_update_all_windows(PCIVPBState *s)
+{
+ /* Update all alias windows based on the current register state */
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ pci_vpb_update_window(s, i);
+ }
+}
+
+static int pci_vpb_post_load(void *opaque, int version_id)
{
- return addr & 0xffffff;
+ PCIVPBState *s = opaque;
+ pci_vpb_update_all_windows(s);
+ return 0;
+}
+
+static const VMStateDescription pci_vpb_vmstate = {
+ .name = "versatile-pci",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = pci_vpb_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(imap, PCIVPBState, 3),
+ VMSTATE_UINT32_ARRAY(smap, PCIVPBState, 3),
+ VMSTATE_UINT32(selfid, PCIVPBState),
+ VMSTATE_UINT32(flags, PCIVPBState),
+ VMSTATE_UINT8(irq_mapping, PCIVPBState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+#define TYPE_VERSATILE_PCI "versatile_pci"
+#define PCI_VPB(obj) \
+ OBJECT_CHECK(PCIVPBState, (obj), TYPE_VERSATILE_PCI)
+
+#define TYPE_VERSATILE_PCI_HOST "versatile_pci_host"
+#define PCI_VPB_HOST(obj) \
+ OBJECT_CHECK(PCIDevice, (obj), TYPE_VERSATILE_PCIHOST)
+
+typedef enum {
+ PCI_IMAP0 = 0x0,
+ PCI_IMAP1 = 0x4,
+ PCI_IMAP2 = 0x8,
+ PCI_SELFID = 0xc,
+ PCI_FLAGS = 0x10,
+ PCI_SMAP0 = 0x14,
+ PCI_SMAP1 = 0x18,
+ PCI_SMAP2 = 0x1c,
+} PCIVPBControlRegs;
+
+static void pci_vpb_reg_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ PCIVPBState *s = opaque;
+
+ switch (addr) {
+ case PCI_IMAP0:
+ case PCI_IMAP1:
+ case PCI_IMAP2:
+ {
+ int win = (addr - PCI_IMAP0) >> 2;
+ s->imap[win] = val;
+ pci_vpb_update_window(s, win);
+ break;
+ }
+ case PCI_SELFID:
+ s->selfid = val;
+ break;
+ case PCI_FLAGS:
+ s->flags = val;
+ break;
+ case PCI_SMAP0:
+ case PCI_SMAP1:
+ case PCI_SMAP2:
+ {
+ int win = (addr - PCI_SMAP0) >> 2;
+ s->smap[win] = val;
+ break;
+ }
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pci_vpb_reg_write: Bad offset %x\n", (int)addr);
+ break;
+ }
+}
+
+static uint64_t pci_vpb_reg_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ PCIVPBState *s = opaque;
+
+ switch (addr) {
+ case PCI_IMAP0:
+ case PCI_IMAP1:
+ case PCI_IMAP2:
+ {
+ int win = (addr - PCI_IMAP0) >> 2;
+ return s->imap[win];
+ }
+ case PCI_SELFID:
+ return s->selfid;
+ case PCI_FLAGS:
+ return s->flags;
+ case PCI_SMAP0:
+ case PCI_SMAP1:
+ case PCI_SMAP2:
+ {
+ int win = (addr - PCI_SMAP0) >> 2;
+ return s->smap[win];
+ }
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pci_vpb_reg_read: Bad offset %x\n", (int)addr);
+ return 0;
+ }
}
+static const MemoryRegionOps pci_vpb_reg_ops = {
+ .read = pci_vpb_reg_read,
+ .write = pci_vpb_reg_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
static void pci_vpb_config_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
- pci_data_write(opaque, vpb_pci_config_addr(addr), val, size);
+ PCIVPBState *s = opaque;
+ if (!s->realview && (addr & 0xff) == PCI_INTERRUPT_LINE
+ && s->irq_mapping == PCI_VPB_IRQMAP_ASSUME_OK) {
+ uint8_t devfn = addr >> 8;
+ if ((PCI_SLOT(devfn) % PCI_NUM_PINS) != 2) {
+ if (val == 27) {
+ s->irq_mapping = PCI_VPB_IRQMAP_BROKEN;
+ } else {
+ s->irq_mapping = PCI_VPB_IRQMAP_FORCE_OK;
+ }
+ }
+ }
+ pci_data_write(&s->pci_bus, addr, val, size);
}
static uint64_t pci_vpb_config_read(void *opaque, hwaddr addr,
unsigned size)
{
+ PCIVPBState *s = opaque;
uint32_t val;
- val = pci_data_read(opaque, vpb_pci_config_addr(addr), size);
+ val = pci_data_read(&s->pci_bus, addr, size);
return val;
}
@@ -48,7 +249,47 @@ static const MemoryRegionOps pci_vpb_config_ops = {
static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
{
- return irq_num;
+ PCIVPBState *s = container_of(d->bus, PCIVPBState, pci_bus);
+
+ if (s->irq_mapping == PCI_VPB_IRQMAP_BROKEN) {
+ /* Legacy broken IRQ mapping for compatibility with old and
+ * buggy Linux guests
+ */
+ return irq_num;
+ }
+
+ /* Slot to IRQ mapping for RealView Platform Baseboard 926 backplane
+ * name slot IntA IntB IntC IntD
+ * A 31 IRQ28 IRQ29 IRQ30 IRQ27
+ * B 30 IRQ27 IRQ28 IRQ29 IRQ30
+ * C 29 IRQ30 IRQ27 IRQ28 IRQ29
+ * Slot C is for the host bridge; A and B the peripherals.
+ * Our output irqs 0..3 correspond to the baseboard's 27..30.
+ *
+ * This mapping function takes account of an oddity in the PB926
+ * board wiring, where the FPGA's P_nINTA input is connected to
+ * the INTB connection on the board PCI edge connector, P_nINTB
+ * is connected to INTC, and so on, so everything is one number
+ * further round from where you might expect.
+ */
+ return pci_swizzle_map_irq_fn(d, irq_num + 2);
+}
+
+static int pci_vpb_rv_map_irq(PCIDevice *d, int irq_num)
+{
+ /* Slot to IRQ mapping for RealView EB and PB1176 backplane
+ * name slot IntA IntB IntC IntD
+ * A 31 IRQ50 IRQ51 IRQ48 IRQ49
+ * B 30 IRQ49 IRQ50 IRQ51 IRQ48
+ * C 29 IRQ48 IRQ49 IRQ50 IRQ51
+ * Slot C is for the host bridge; A and B the peripherals.
+ * Our output irqs 0..3 correspond to the baseboard's 48..51.
+ *
+ * The PB1176 and EB boards don't have the PB926 wiring oddity
+ * described above; P_nINTA connects to INTA, P_nINTB to INTB
+ * and so on, which is why this mapping function is different.
+ */
+ return pci_swizzle_map_irq_fn(d, irq_num + 3);
}
static void pci_vpb_set_irq(void *opaque, int irq_num, int level)
@@ -58,53 +299,109 @@ static void pci_vpb_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pic[irq_num], level);
}
-static int pci_vpb_init(SysBusDevice *dev)
+static void pci_vpb_reset(DeviceState *d)
+{
+ PCIVPBState *s = PCI_VPB(d);
+
+ s->imap[0] = 0;
+ s->imap[1] = 0;
+ s->imap[2] = 0;
+ s->smap[0] = 0;
+ s->smap[1] = 0;
+ s->smap[2] = 0;
+ s->selfid = 0;
+ s->flags = 0;
+ s->irq_mapping = PCI_VPB_IRQMAP_ASSUME_OK;
+
+ pci_vpb_update_all_windows(s);
+}
+
+static void pci_vpb_init(Object *obj)
{
- PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
- PCIBus *bus;
+ PCIHostState *h = PCI_HOST_BRIDGE(obj);
+ PCIVPBState *s = PCI_VPB(obj);
+
+ memory_region_init(&s->pci_io_space, "pci_io", 1ULL << 32);
+ memory_region_init(&s->pci_mem_space, "pci_mem", 1ULL << 32);
+
+ pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), "pci",
+ &s->pci_mem_space, &s->pci_io_space,
+ PCI_DEVFN(11, 0), TYPE_PCI_BUS);
+ h->bus = &s->pci_bus;
+
+ object_initialize(&s->pci_dev, TYPE_VERSATILE_PCI_HOST);
+ qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus));
+ object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(29, 0), "addr",
+ NULL);
+
+ /* Window sizes for VersatilePB; realview_pci's init will override */
+ s->mem_win_size[0] = 0x0c000000;
+ s->mem_win_size[1] = 0x10000000;
+ s->mem_win_size[2] = 0x10000000;
+}
+
+static void pci_vpb_realize(DeviceState *dev, Error **errp)
+{
+ PCIVPBState *s = PCI_VPB(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ pci_map_irq_fn mapfn;
int i;
for (i = 0; i < 4; i++) {
- sysbus_init_irq(dev, &s->irq[i]);
+ sysbus_init_irq(sbd, &s->irq[i]);
+ }
+
+ if (s->realview) {
+ mapfn = pci_vpb_rv_map_irq;
+ } else {
+ mapfn = pci_vpb_map_irq;
}
- bus = pci_register_bus(&dev->qdev, "pci",
- pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
- get_system_memory(), get_system_io(),
- PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
- /* ??? Register memory space. */
+ pci_bus_irqs(&s->pci_bus, pci_vpb_set_irq, mapfn, s->irq, 4);
/* Our memory regions are:
- * 0 : PCI self config window
- * 1 : PCI config window
- * 2 : PCI IO window (realview_pci only)
+ * 0 : our control registers
+ * 1 : PCI self config window
+ * 2 : PCI config window
+ * 3 : PCI IO window
+ * 4..6 : PCI memory windows
*/
- memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, bus,
+ memory_region_init_io(&s->controlregs, &pci_vpb_reg_ops, s, "pci-vpb-regs",
+ 0x1000);
+ sysbus_init_mmio(sbd, &s->controlregs);
+ memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, s,
"pci-vpb-selfconfig", 0x1000000);
- sysbus_init_mmio(dev, &s->mem_config);
- memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, bus,
+ sysbus_init_mmio(sbd, &s->mem_config);
+ memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, s,
"pci-vpb-config", 0x1000000);
- sysbus_init_mmio(dev, &s->mem_config2);
- if (s->realview) {
- isa_mmio_setup(&s->isa, 0x0100000);
- sysbus_init_mmio(dev, &s->isa);
- }
+ sysbus_init_mmio(sbd, &s->mem_config2);
- pci_create_simple(bus, -1, "versatile_pci_host");
- return 0;
-}
+ /* The window into I/O space is always into a fixed base address;
+ * its size is the same for both realview and versatile.
+ */
+ memory_region_init_alias(&s->pci_io_window, "pci-vbp-io-window",
+ &s->pci_io_space, 0, 0x100000);
-static int pci_realview_init(SysBusDevice *dev)
-{
- PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
- s->realview = 1;
- return pci_vpb_init(dev);
+ sysbus_init_mmio(sbd, &s->pci_io_space);
+
+ /* Create the alias regions corresponding to our three windows onto
+ * PCI memory space. The sizes vary from board to board; the base
+ * offsets are guest controllable via the IMAP registers.
+ */
+ for (i = 0; i < 3; i++) {
+ memory_region_init_alias(&s->pci_mem_window[i], "pci-vbp-window",
+ &s->pci_mem_space, 0, s->mem_win_size[i]);
+ sysbus_init_mmio(sbd, &s->pci_mem_window[i]);
+ }
+
+ /* TODO Remove once realize propagates to child devices. */
+ object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
}
static int versatile_pci_host_init(PCIDevice *d)
{
pci_set_word(d->config + PCI_STATUS,
- PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
+ PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
return 0;
}
@@ -120,7 +417,7 @@ static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo versatile_pci_host_info = {
- .name = "versatile_pci_host",
+ .name = TYPE_VERSATILE_PCI_HOST,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PCIDevice),
.class_init = versatile_pci_host_class_init,
@@ -128,30 +425,36 @@ static const TypeInfo versatile_pci_host_info = {
static void pci_vpb_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
- sdc->init = pci_vpb_init;
+ dc->realize = pci_vpb_realize;
+ dc->reset = pci_vpb_reset;
+ dc->vmsd = &pci_vpb_vmstate;
}
static const TypeInfo pci_vpb_info = {
- .name = "versatile_pci",
- .parent = TYPE_SYS_BUS_DEVICE,
+ .name = TYPE_VERSATILE_PCI,
+ .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(PCIVPBState),
+ .instance_init = pci_vpb_init,
.class_init = pci_vpb_class_init,
};
-static void pci_realview_class_init(ObjectClass *klass, void *data)
+static void pci_realview_init(Object *obj)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ PCIVPBState *s = PCI_VPB(obj);
- sdc->init = pci_realview_init;
+ s->realview = 1;
+ /* The PCI window sizes are different on Realview boards */
+ s->mem_win_size[0] = 0x01000000;
+ s->mem_win_size[1] = 0x04000000;
+ s->mem_win_size[2] = 0x08000000;
}
static const TypeInfo pci_realview_info = {
.name = "realview_pci",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(PCIVPBState),
- .class_init = pci_realview_class_init,
+ .parent = TYPE_VERSATILE_PCI,
+ .instance_init = pci_realview_init,
};
static void versatile_pci_register_types(void)
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 8e56b16648..f0c7ee9abd 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -337,7 +337,7 @@ static void ref405ep_init(QEMUMachineInitArgs *args)
if (kernel_cmdline != NULL) {
len = strlen(kernel_cmdline);
bdloc -= ((len + 255) & ~255);
- cpu_physical_memory_write(bdloc, (void *)kernel_cmdline, len + 1);
+ cpu_physical_memory_write(bdloc, kernel_cmdline, len + 1);
env->gpr[6] = bdloc;
env->gpr[7] = bdloc + len;
} else {
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 6728ba7ea0..1b4ce760e6 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -161,7 +161,7 @@ static int xilinx_load_device_tree(hwaddr addr,
r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline);
if (r < 0)
fprintf(stderr, "couldn't set /chosen/bootargs\n");
- cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
+ cpu_physical_memory_write(addr, fdt, fdt_size);
#else
/* We lack libfdt so we cannot manipulate the fdt. Just pass on the blob
to the kernel. */
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 31beb32885..635115f097 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -37,7 +37,6 @@
#include "hw/nvram/fw_cfg.h"
#include "hw/char/escc.h"
#include "hw/empty_slot.h"
-#include "hw/qdev-addr.h"
#include "hw/loader.h"
#include "elf.h"
#include "sysemu/blockdev.h"
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index c2c446eb9b..76e32ceef8 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -275,7 +275,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
dev->actual = le32_to_cpu(config.actual);
if (dev->actual != oldactual) {
qemu_balloon_changed(ram_size -
- (dev->actual << VIRTIO_BALLOON_PFN_SHIFT));
+ ((ram_addr_t) dev->actual << VIRTIO_BALLOON_PFN_SHIFT));
}
}
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 2c138b185f..8d075ab5a3 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -86,6 +86,7 @@
#define PCI_DEVICE_ID_REDHAT_SERIAL 0x0002
#define PCI_DEVICE_ID_REDHAT_SERIAL2 0x0003
#define PCI_DEVICE_ID_REDHAT_SERIAL4 0x0004
+#define PCI_DEVICE_ID_REDHAT_TEST 0x0005
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
#define FMT_PCIBUS PRIx64
diff --git a/include/hw/qdev-addr.h b/include/hw/qdev-addr.h
deleted file mode 100644
index 79708e6751..0000000000
--- a/include/hw/qdev-addr.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef HW_QDEV_ADDR_H
-#define HW_QDEV_ADDR_H 1
-
-#define DEFINE_PROP_TADDR(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_taddr, hwaddr)
-
-extern PropertyInfo qdev_prop_taddr;
-void qdev_prop_set_taddr(DeviceState *dev, const char *name, hwaddr value);
-
-#endif
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index b21e5c2b9d..d3f14366dc 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -258,7 +258,6 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
uint32_t host_features);
typedef struct virtio_serial_conf virtio_serial_conf;
VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
-VirtIODevice *virtio_balloon_init(DeviceState *dev);
typedef struct VirtIOSCSIConf VirtIOSCSIConf;
VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
typedef struct VirtIORNGConf VirtIORNGConf;
@@ -270,7 +269,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
void virtio_net_exit(VirtIODevice *vdev);
void virtio_serial_exit(VirtIODevice *vdev);
-void virtio_balloon_exit(VirtIODevice *vdev);
void virtio_scsi_exit(VirtIODevice *vdev);
void virtio_rng_exit(VirtIODevice *vdev);
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index d3af35d1d9..14a5f657ce 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -4,6 +4,7 @@
#include "config-host.h"
#include <inttypes.h>
#include <limits.h>
+#include <string.h>
#include "fpu/softfloat.h"
#ifdef CONFIG_MACHINE_BSWAP_H
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 495e6f8dbd..75bd7d9934 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -283,10 +283,6 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
#endif
#endif
-int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign,
- uint32_t size);
-
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
diff --git a/kvm-all.c b/kvm-all.c
index fc4e17c8bb..2d927217bd 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -500,6 +500,66 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return ret;
}
+static int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val,
+ bool assign, uint32_t size, bool datamatch)
+{
+ int ret;
+ struct kvm_ioeventfd iofd;
+
+ iofd.datamatch = datamatch ? val : 0;
+ iofd.addr = addr;
+ iofd.len = size;
+ iofd.flags = 0;
+ iofd.fd = fd;
+
+ if (!kvm_enabled()) {
+ return -ENOSYS;
+ }
+
+ if (datamatch) {
+ iofd.flags |= KVM_IOEVENTFD_FLAG_DATAMATCH;
+ }
+ if (!assign) {
+ iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+ }
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &iofd);
+
+ if (ret < 0) {
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint16_t val,
+ bool assign, uint32_t size, bool datamatch)
+{
+ struct kvm_ioeventfd kick = {
+ .datamatch = datamatch ? val : 0,
+ .addr = addr,
+ .flags = KVM_IOEVENTFD_FLAG_PIO,
+ .len = size,
+ .fd = fd,
+ };
+ int r;
+ if (!kvm_enabled()) {
+ return -ENOSYS;
+ }
+ if (datamatch) {
+ kick.flags |= KVM_IOEVENTFD_FLAG_DATAMATCH;
+ }
+ if (!assign) {
+ kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+ }
+ r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+
+
static int kvm_check_many_ioeventfds(void)
{
/* Userspace can use ioeventfd for io notification. This requires a host
@@ -517,7 +577,7 @@ static int kvm_check_many_ioeventfds(void)
if (ioeventfds[i] < 0) {
break;
}
- ret = kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, true);
+ ret = kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, true, 2, true);
if (ret < 0) {
close(ioeventfds[i]);
break;
@@ -528,7 +588,7 @@ static int kvm_check_many_ioeventfds(void)
ret = i == ARRAY_SIZE(ioeventfds);
while (i-- > 0) {
- kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, false);
+ kvm_set_ioeventfd_pio(ioeventfds[i], 0, i, false, 2, true);
close(ioeventfds[i]);
}
return ret;
@@ -748,10 +808,8 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
int fd = event_notifier_get_fd(e);
int r;
- assert(match_data && section->size <= 8);
-
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
- data, true, section->size);
+ data, true, section->size, match_data);
if (r < 0) {
abort();
}
@@ -766,7 +824,7 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
int r;
r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
- data, false, section->size);
+ data, false, section->size, match_data);
if (r < 0) {
abort();
}
@@ -780,10 +838,8 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener,
int fd = event_notifier_get_fd(e);
int r;
- assert(match_data && section->size == 2);
-
- r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
- data, true);
+ r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
+ data, true, section->size, match_data);
if (r < 0) {
abort();
}
@@ -798,8 +854,8 @@ static void kvm_io_ioeventfd_del(MemoryListener *listener,
int fd = event_notifier_get_fd(e);
int r;
- r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
- data, false);
+ r = kvm_set_ioeventfd_pio(fd, section->offset_within_address_space,
+ data, false, section->size, match_data);
if (r < 0) {
abort();
}
@@ -1967,59 +2023,6 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
return r;
}
-
-int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool assign,
- uint32_t size)
-{
- int ret;
- struct kvm_ioeventfd iofd;
-
- iofd.datamatch = val;
- iofd.addr = addr;
- iofd.len = size;
- iofd.flags = KVM_IOEVENTFD_FLAG_DATAMATCH;
- iofd.fd = fd;
-
- if (!kvm_enabled()) {
- return -ENOSYS;
- }
-
- if (!assign) {
- iofd.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
- }
-
- ret = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &iofd);
-
- if (ret < 0) {
- return -errno;
- }
-
- return 0;
-}
-
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
-{
- struct kvm_ioeventfd kick = {
- .datamatch = val,
- .addr = addr,
- .len = 2,
- .flags = KVM_IOEVENTFD_FLAG_DATAMATCH | KVM_IOEVENTFD_FLAG_PIO,
- .fd = fd,
- };
- int r;
- if (!kvm_enabled()) {
- return -ENOSYS;
- }
- if (!assign) {
- kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
- }
- r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
- if (r < 0) {
- return r;
- }
- return 0;
-}
-
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
{
return kvm_arch_on_sigbus_vcpu(cpu, code, addr);
diff --git a/kvm-stub.c b/kvm-stub.c
index 723a813735..5f52186ae7 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -101,16 +101,6 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
}
#endif
-int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
-{
- return -ENOSYS;
-}
-
-int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign, uint32_t len)
-{
- return -ENOSYS;
-}
-
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
{
return 1;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1f07621ffe..c705960d7e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -914,7 +914,7 @@ static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
for (i = 0; i < nw; i++) {
v = 0;
for (j = 0; j < TARGET_ABI_BITS; j++) {
- v |= ((FD_ISSET(k, fds) != 0) << j);
+ v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
k++;
}
__put_user(v, &target_fds[i]);
@@ -2764,7 +2764,7 @@ static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
if (target_to_host_sembuf(sops, ptr, nsops))
return -TARGET_EFAULT;
- return semop(semid, sops, nsops);
+ return get_errno(semop(semid, sops, nsops));
}
struct target_msqid_ds
@@ -6957,7 +6957,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_semop
case TARGET_NR_semop:
- ret = get_errno(do_semop(arg1, arg2, arg3));
+ ret = do_semop(arg1, arg2, arg3);
break;
#endif
#ifdef TARGET_NR_semctl
@@ -7743,12 +7743,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (gidsetsize == 0)
break;
if (!is_error(ret)) {
- target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
+ target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
if (!target_grouplist)
goto efault;
for(i = 0;i < ret; i++)
target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
- unlock_user(target_grouplist, arg2, gidsetsize * 2);
+ unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
}
}
break;
@@ -7760,7 +7760,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
int i;
if (gidsetsize) {
grouplist = alloca(gidsetsize * sizeof(gid_t));
- target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
+ target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
if (!target_grouplist) {
ret = -TARGET_EFAULT;
goto fail;
diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap
index 0b23f7795a..c90eda497a 100755
--- a/scripts/kvm/vmxcap
+++ b/scripts/kvm/vmxcap
@@ -27,9 +27,9 @@ MSR_IA32_VMX_VMFUNC = 0x491
class msr(object):
def __init__(self):
try:
- self.f = file('/dev/cpu/0/msr')
+ self.f = open('/dev/cpu/0/msr', 'r', 0)
except:
- self.f = file('/dev/msr0')
+ self.f = open('/dev/msr0', 'r', 0)
def read(self, index, default = None):
import struct
self.f.seek(index)
@@ -96,6 +96,19 @@ class Misc(object):
print ' %-40s %s' % (self.bits[bits], fmt(v))
controls = [
+ Misc(
+ name = 'Basic VMX Information',
+ bits = {
+ (0, 31): 'Revision',
+ (32,44): 'VMCS size',
+ 48: 'VMCS restricted to 32 bit addresses',
+ 49: 'Dual-monitor support',
+ (50, 53): 'VMCS memory type',
+ 54: 'INS/OUTS instruction information',
+ 55: 'IA32_VMX_TRUE_*_CTLS support',
+ },
+ msr = MSR_IA32_VMX_BASIC,
+ ),
Control(
name = 'pin-based controls',
bits = {
@@ -103,6 +116,7 @@ controls = [
3: 'NMI exiting',
5: 'Virtual NMIs',
6: 'Activate VMX-preemption timer',
+ 7: 'Process posted interrupts',
},
cap_msr = MSR_IA32_VMX_PINBASED_CTLS,
true_cap_msr = MSR_IA32_VMX_TRUE_PINBASED_CTLS,
@@ -143,15 +157,19 @@ controls = [
0: 'Virtualize APIC accesses',
1: 'Enable EPT',
2: 'Descriptor-table exiting',
+ 3: 'Enable RDTSCP',
4: 'Virtualize x2APIC mode',
5: 'Enable VPID',
6: 'WBINVD exiting',
7: 'Unrestricted guest',
+ 8: 'APIC register emulation',
9: 'Virtual interrupt delivery',
10: 'PAUSE-loop exiting',
11: 'RDRAND exiting',
12: 'Enable INVPCID',
13: 'Enable VM functions',
+ 14: 'VMCS shadowing',
+ 18: 'EPT-violation #VE'
},
cap_msr = MSR_IA32_VMX_PROCBASED_CTLS2,
),
@@ -196,10 +214,12 @@ controls = [
6: 'HLT activity state',
7: 'Shutdown activity state',
8: 'Wait-for-SIPI activity state',
+ 15: 'IA32_SMBASE support',
(16,24): 'Number of CR3-target values',
(25,27): 'MSR-load/store count recommenation',
28: 'IA32_SMM_MONITOR_CTL[2] can be set to 1',
- (32,62): 'MSEG revision identifier',
+ 29: 'VMWRITE to VM-exit information fields',
+ (32,63): 'MSEG revision identifier',
},
msr = MSR_IA32_VMX_MISC_CTLS,
),
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 25895509be..12fcefe0c6 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -111,6 +111,10 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
#define ENV_OFFSET offsetof(ARMCPU, env)
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vmstate_arm_cpu;
+#endif
+
void register_cp_regs_for_features(ARMCPU *cpu);
void arm_cpu_do_interrupt(CPUState *cpu);
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index a1e90939d6..496a59f5c0 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -814,6 +814,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = arm_cpu_class_by_name;
cc->do_interrupt = arm_cpu_do_interrupt;
+ cpu_class_set_vmsd(cc, &vmstate_arm_cpu);
}
static void cpu_register(const ARMCPUInfo *info)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2b97221209..54384446b4 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -640,8 +640,6 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
#define cpu_signal_handler cpu_arm_signal_handler
#define cpu_list arm_cpu_list
-#define CPU_SAVE_VERSION 9
-
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _kernel
#define MMU_MODE1_SUFFIX _user
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 68dca7ffb2..4dd057c488 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -1,237 +1,239 @@
#include "hw/hw.h"
#include "hw/boards.h"
-void cpu_save(QEMUFile *f, void *opaque)
+static bool vfp_needed(void *opaque)
{
- int i;
- CPUARMState *env = (CPUARMState *)opaque;
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
- for (i = 0; i < 16; i++) {
- qemu_put_be32(f, env->regs[i]);
- }
- qemu_put_be32(f, cpsr_read(env));
- qemu_put_be32(f, env->spsr);
- for (i = 0; i < 6; i++) {
- qemu_put_be32(f, env->banked_spsr[i]);
- qemu_put_be32(f, env->banked_r13[i]);
- qemu_put_be32(f, env->banked_r14[i]);
- }
- for (i = 0; i < 5; i++) {
- qemu_put_be32(f, env->usr_regs[i]);
- qemu_put_be32(f, env->fiq_regs[i]);
- }
- qemu_put_be32(f, env->cp15.c0_cpuid);
- qemu_put_be32(f, env->cp15.c0_cssel);
- qemu_put_be32(f, env->cp15.c1_sys);
- qemu_put_be32(f, env->cp15.c1_coproc);
- qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
- qemu_put_be32(f, env->cp15.c1_scr);
- qemu_put_be32(f, env->cp15.c2_base0);
- qemu_put_be32(f, env->cp15.c2_base0_hi);
- qemu_put_be32(f, env->cp15.c2_base1);
- qemu_put_be32(f, env->cp15.c2_base1_hi);
- qemu_put_be32(f, env->cp15.c2_control);
- qemu_put_be32(f, env->cp15.c2_mask);
- qemu_put_be32(f, env->cp15.c2_base_mask);
- qemu_put_be32(f, env->cp15.c2_data);
- qemu_put_be32(f, env->cp15.c2_insn);
- qemu_put_be32(f, env->cp15.c3);
- qemu_put_be32(f, env->cp15.c5_insn);
- qemu_put_be32(f, env->cp15.c5_data);
- for (i = 0; i < 8; i++) {
- qemu_put_be32(f, env->cp15.c6_region[i]);
- }
- qemu_put_be32(f, env->cp15.c6_insn);
- qemu_put_be32(f, env->cp15.c6_data);
- qemu_put_be32(f, env->cp15.c7_par);
- qemu_put_be32(f, env->cp15.c7_par_hi);
- qemu_put_be32(f, env->cp15.c9_insn);
- qemu_put_be32(f, env->cp15.c9_data);
- qemu_put_be32(f, env->cp15.c9_pmcr);
- qemu_put_be32(f, env->cp15.c9_pmcnten);
- qemu_put_be32(f, env->cp15.c9_pmovsr);
- qemu_put_be32(f, env->cp15.c9_pmxevtyper);
- qemu_put_be32(f, env->cp15.c9_pmuserenr);
- qemu_put_be32(f, env->cp15.c9_pminten);
- qemu_put_be32(f, env->cp15.c13_fcse);
- qemu_put_be32(f, env->cp15.c13_context);
- qemu_put_be32(f, env->cp15.c13_tls1);
- qemu_put_be32(f, env->cp15.c13_tls2);
- qemu_put_be32(f, env->cp15.c13_tls3);
- qemu_put_be32(f, env->cp15.c15_cpar);
- qemu_put_be32(f, env->cp15.c15_power_control);
- qemu_put_be32(f, env->cp15.c15_diagnostic);
- qemu_put_be32(f, env->cp15.c15_power_diagnostic);
-
- qemu_put_be64(f, env->features);
-
- if (arm_feature(env, ARM_FEATURE_VFP)) {
- for (i = 0; i < 16; i++) {
- CPU_DoubleU u;
- u.d = env->vfp.regs[i];
- qemu_put_be32(f, u.l.upper);
- qemu_put_be32(f, u.l.lower);
- }
- for (i = 0; i < 16; i++) {
- qemu_put_be32(f, env->vfp.xregs[i]);
- }
+ return arm_feature(env, ARM_FEATURE_VFP);
+}
- /* TODO: Should use proper FPSCR access functions. */
- qemu_put_be32(f, env->vfp.vec_len);
- qemu_put_be32(f, env->vfp.vec_stride);
-
- if (arm_feature(env, ARM_FEATURE_VFP3)) {
- for (i = 16; i < 32; i++) {
- CPU_DoubleU u;
- u.d = env->vfp.regs[i];
- qemu_put_be32(f, u.l.upper);
- qemu_put_be32(f, u.l.lower);
- }
- }
- }
+static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+ uint32_t val = qemu_get_be32(f);
- if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
- for (i = 0; i < 16; i++) {
- qemu_put_be64(f, env->iwmmxt.regs[i]);
- }
- for (i = 0; i < 16; i++) {
- qemu_put_be32(f, env->iwmmxt.cregs[i]);
- }
- }
+ vfp_set_fpscr(env, val);
+ return 0;
+}
- if (arm_feature(env, ARM_FEATURE_M)) {
- qemu_put_be32(f, env->v7m.other_sp);
- qemu_put_be32(f, env->v7m.vecbase);
- qemu_put_be32(f, env->v7m.basepri);
- qemu_put_be32(f, env->v7m.control);
- qemu_put_be32(f, env->v7m.current_sp);
- qemu_put_be32(f, env->v7m.exception);
- }
+static void put_fpscr(QEMUFile *f, void *opaque, size_t size)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
- if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
- qemu_put_be32(f, env->teecr);
- qemu_put_be32(f, env->teehbr);
- }
+ qemu_put_be32(f, vfp_get_fpscr(env));
}
-int cpu_load(QEMUFile *f, void *opaque, int version_id)
+static const VMStateInfo vmstate_fpscr = {
+ .name = "fpscr",
+ .get = get_fpscr,
+ .put = put_fpscr,
+};
+
+static const VMStateDescription vmstate_vfp = {
+ .name = "cpu/vfp",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField[]) {
+ VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 32),
+ /* The xregs array is a little awkward because element 1 (FPSCR)
+ * requires a specific accessor, so we have to split it up in
+ * the vmstate:
+ */
+ VMSTATE_UINT32(env.vfp.xregs[0], ARMCPU),
+ VMSTATE_UINT32_SUB_ARRAY(env.vfp.xregs, ARMCPU, 2, 14),
+ {
+ .name = "fpscr",
+ .version_id = 0,
+ .size = sizeof(uint32_t),
+ .info = &vmstate_fpscr,
+ .flags = VMS_SINGLE,
+ .offset = 0,
+ },
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static bool iwmmxt_needed(void *opaque)
{
- CPUARMState *env = (CPUARMState *)opaque;
- int i;
- uint32_t val;
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
- if (version_id != CPU_SAVE_VERSION)
- return -EINVAL;
+ return arm_feature(env, ARM_FEATURE_IWMMXT);
+}
- for (i = 0; i < 16; i++) {
- env->regs[i] = qemu_get_be32(f);
- }
- val = qemu_get_be32(f);
- /* Avoid mode switch when restoring CPSR. */
- env->uncached_cpsr = val & CPSR_M;
- cpsr_write(env, val, 0xffffffff);
- env->spsr = qemu_get_be32(f);
- for (i = 0; i < 6; i++) {
- env->banked_spsr[i] = qemu_get_be32(f);
- env->banked_r13[i] = qemu_get_be32(f);
- env->banked_r14[i] = qemu_get_be32(f);
- }
- for (i = 0; i < 5; i++) {
- env->usr_regs[i] = qemu_get_be32(f);
- env->fiq_regs[i] = qemu_get_be32(f);
- }
- env->cp15.c0_cpuid = qemu_get_be32(f);
- env->cp15.c0_cssel = qemu_get_be32(f);
- env->cp15.c1_sys = qemu_get_be32(f);
- env->cp15.c1_coproc = qemu_get_be32(f);
- env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
- env->cp15.c1_scr = qemu_get_be32(f);
- env->cp15.c2_base0 = qemu_get_be32(f);
- env->cp15.c2_base0_hi = qemu_get_be32(f);
- env->cp15.c2_base1 = qemu_get_be32(f);
- env->cp15.c2_base1_hi = qemu_get_be32(f);
- env->cp15.c2_control = qemu_get_be32(f);
- env->cp15.c2_mask = qemu_get_be32(f);
- env->cp15.c2_base_mask = qemu_get_be32(f);
- env->cp15.c2_data = qemu_get_be32(f);
- env->cp15.c2_insn = qemu_get_be32(f);
- env->cp15.c3 = qemu_get_be32(f);
- env->cp15.c5_insn = qemu_get_be32(f);
- env->cp15.c5_data = qemu_get_be32(f);
- for (i = 0; i < 8; i++) {
- env->cp15.c6_region[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_iwmmxt = {
+ .name = "cpu/iwmmxt",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16),
+ VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16),
+ VMSTATE_END_OF_LIST()
}
- env->cp15.c6_insn = qemu_get_be32(f);
- env->cp15.c6_data = qemu_get_be32(f);
- env->cp15.c7_par = qemu_get_be32(f);
- env->cp15.c7_par_hi = qemu_get_be32(f);
- env->cp15.c9_insn = qemu_get_be32(f);
- env->cp15.c9_data = qemu_get_be32(f);
- env->cp15.c9_pmcr = qemu_get_be32(f);
- env->cp15.c9_pmcnten = qemu_get_be32(f);
- env->cp15.c9_pmovsr = qemu_get_be32(f);
- env->cp15.c9_pmxevtyper = qemu_get_be32(f);
- env->cp15.c9_pmuserenr = qemu_get_be32(f);
- env->cp15.c9_pminten = qemu_get_be32(f);
- env->cp15.c13_fcse = qemu_get_be32(f);
- env->cp15.c13_context = qemu_get_be32(f);
- env->cp15.c13_tls1 = qemu_get_be32(f);
- env->cp15.c13_tls2 = qemu_get_be32(f);
- env->cp15.c13_tls3 = qemu_get_be32(f);
- env->cp15.c15_cpar = qemu_get_be32(f);
- env->cp15.c15_power_control = qemu_get_be32(f);
- env->cp15.c15_diagnostic = qemu_get_be32(f);
- env->cp15.c15_power_diagnostic = qemu_get_be32(f);
-
- env->features = qemu_get_be64(f);
-
- if (arm_feature(env, ARM_FEATURE_VFP)) {
- for (i = 0; i < 16; i++) {
- CPU_DoubleU u;
- u.l.upper = qemu_get_be32(f);
- u.l.lower = qemu_get_be32(f);
- env->vfp.regs[i] = u.d;
- }
- for (i = 0; i < 16; i++) {
- env->vfp.xregs[i] = qemu_get_be32(f);
- }
+};
- /* TODO: Should use proper FPSCR access functions. */
- env->vfp.vec_len = qemu_get_be32(f);
- env->vfp.vec_stride = qemu_get_be32(f);
-
- if (arm_feature(env, ARM_FEATURE_VFP3)) {
- for (i = 16; i < 32; i++) {
- CPU_DoubleU u;
- u.l.upper = qemu_get_be32(f);
- u.l.lower = qemu_get_be32(f);
- env->vfp.regs[i] = u.d;
- }
- }
- }
+static bool m_needed(void *opaque)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
- if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
- for (i = 0; i < 16; i++) {
- env->iwmmxt.regs[i] = qemu_get_be64(f);
- }
- for (i = 0; i < 16; i++) {
- env->iwmmxt.cregs[i] = qemu_get_be32(f);
- }
- }
+ return arm_feature(env, ARM_FEATURE_M);
+}
- if (arm_feature(env, ARM_FEATURE_M)) {
- env->v7m.other_sp = qemu_get_be32(f);
- env->v7m.vecbase = qemu_get_be32(f);
- env->v7m.basepri = qemu_get_be32(f);
- env->v7m.control = qemu_get_be32(f);
- env->v7m.current_sp = qemu_get_be32(f);
- env->v7m.exception = qemu_get_be32(f);
- }
+const VMStateDescription vmstate_m = {
+ .name = "cpu/m",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(env.v7m.other_sp, ARMCPU),
+ VMSTATE_UINT32(env.v7m.vecbase, ARMCPU),
+ VMSTATE_UINT32(env.v7m.basepri, ARMCPU),
+ VMSTATE_UINT32(env.v7m.control, ARMCPU),
+ VMSTATE_INT32(env.v7m.current_sp, ARMCPU),
+ VMSTATE_INT32(env.v7m.exception, ARMCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static bool thumb2ee_needed(void *opaque)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+
+ return arm_feature(env, ARM_FEATURE_THUMB2EE);
+}
- if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
- env->teecr = qemu_get_be32(f);
- env->teehbr = qemu_get_be32(f);
+static const VMStateDescription vmstate_thumb2ee = {
+ .name = "cpu/thumb2ee",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(env.teecr, ARMCPU),
+ VMSTATE_UINT32(env.teehbr, ARMCPU),
+ VMSTATE_END_OF_LIST()
}
+};
+static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+ uint32_t val = qemu_get_be32(f);
+
+ /* Avoid mode switch when restoring CPSR */
+ env->uncached_cpsr = val & CPSR_M;
+ cpsr_write(env, val, 0xffffffff);
return 0;
}
+
+static void put_cpsr(QEMUFile *f, void *opaque, size_t size)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+
+ qemu_put_be32(f, cpsr_read(env));
+}
+
+static const VMStateInfo vmstate_cpsr = {
+ .name = "cpsr",
+ .get = get_cpsr,
+ .put = put_cpsr,
+};
+
+const VMStateDescription vmstate_arm_cpu = {
+ .name = "cpu",
+ .version_id = 11,
+ .minimum_version_id = 11,
+ .minimum_version_id_old = 11,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16),
+ {
+ .name = "cpsr",
+ .version_id = 0,
+ .size = sizeof(uint32_t),
+ .info = &vmstate_cpsr,
+ .flags = VMS_SINGLE,
+ .offset = 0,
+ },
+ VMSTATE_UINT32(env.spsr, ARMCPU),
+ VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 6),
+ VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
+ VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
+ VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
+ VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
+ VMSTATE_UINT32(env.cp15.c0_cpuid, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c0_cssel, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c1_sys, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c1_coproc, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c1_xscaleauxcr, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c1_scr, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_base0, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_base0_hi, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_base1, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_base1_hi, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_control, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_mask, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_base_mask, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_data, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c2_insn, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c3, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c5_insn, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c5_data, ARMCPU),
+ VMSTATE_UINT32_ARRAY(env.cp15.c6_region, ARMCPU, 8),
+ VMSTATE_UINT32(env.cp15.c6_insn, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c6_data, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c7_par, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c7_par_hi, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_insn, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_data, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_pmcr, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_pmcnten, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_pmovsr, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_pmxevtyper, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_pmuserenr, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c9_pminten, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c13_fcse, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c13_context, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c13_tls1, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c13_tls2, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c13_tls3, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_cpar, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_ticonfig, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_i_max, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_i_min, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_threadid, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_power_control, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_diagnostic, ARMCPU),
+ VMSTATE_UINT32(env.cp15.c15_power_diagnostic, ARMCPU),
+ VMSTATE_UINT32(env.exclusive_addr, ARMCPU),
+ VMSTATE_UINT32(env.exclusive_val, ARMCPU),
+ VMSTATE_UINT32(env.exclusive_high, ARMCPU),
+ VMSTATE_UINT64(env.features, ARMCPU),
+ VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection[]) {
+ {
+ .vmsd = &vmstate_vfp,
+ .needed = vfp_needed,
+ } , {
+ .vmsd = &vmstate_iwmmxt,
+ .needed = iwmmxt_needed,
+ } , {
+ .vmsd = &vmstate_m,
+ .needed = m_needed,
+ } , {
+ .vmsd = &vmstate_thumb2ee,
+ .needed = thumb2ee_needed,
+ } , {
+ /* empty */
+ }
+ }
+};
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 35a21be931..a1b7b8c1a8 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6762,6 +6762,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
}
ARCH(6);
gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
+ return;
} else if ((insn & 0x0e50ffe0) == 0x08100a00) {
/* rfe */
int32_t offset;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index cf1b05c28c..a1614e8e50 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -803,6 +803,7 @@ typedef struct CPUX86State {
#endif
uint64_t system_time_msr;
uint64_t wall_clock_msr;
+ uint64_t steal_time_msr;
uint64_t async_pf_en_msr;
uint64_t pv_eoi_en_msr;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 397afebecb..0e7cc8113f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -68,6 +68,7 @@ static bool has_msr_tsc_deadline;
static bool has_msr_async_pf_en;
static bool has_msr_pv_eoi_en;
static bool has_msr_misc_enable;
+static bool has_msr_kvm_steal_time;
static int lm_capable_kernel;
bool kvm_allows_irq0_override(void)
@@ -507,6 +508,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI);
+ has_msr_kvm_steal_time = c->eax & (1 << KVM_FEATURE_STEAL_TIME);
+
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
for (i = 0; i <= limit; i++) {
@@ -1107,6 +1110,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_set(&msrs[n++], MSR_KVM_PV_EOI_EN,
env->pv_eoi_en_msr);
}
+ if (has_msr_kvm_steal_time) {
+ kvm_msr_entry_set(&msrs[n++], MSR_KVM_STEAL_TIME,
+ env->steal_time_msr);
+ }
if (hyperv_hypercall_available()) {
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
@@ -1360,6 +1367,9 @@ static int kvm_get_msrs(X86CPU *cpu)
if (has_msr_pv_eoi_en) {
msrs[n++].index = MSR_KVM_PV_EOI_EN;
}
+ if (has_msr_kvm_steal_time) {
+ msrs[n++].index = MSR_KVM_STEAL_TIME;
+ }
if (env->mcg_cap) {
msrs[n++].index = MSR_MCG_STATUS;
@@ -1445,6 +1455,9 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_KVM_PV_EOI_EN:
env->pv_eoi_en_msr = msrs[i].data;
break;
+ case MSR_KVM_STEAL_TIME:
+ env->steal_time_msr = msrs[i].data;
+ break;
}
}
diff --git a/target-i386/machine.c b/target-i386/machine.c
index ee85e57435..3659db9e94 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -292,6 +292,24 @@ static bool pv_eoi_msr_needed(void *opaque)
return cpu->env.pv_eoi_en_msr != 0;
}
+static bool steal_time_msr_needed(void *opaque)
+{
+ CPUX86State *cpu = opaque;
+
+ return cpu->steal_time_msr != 0;
+}
+
+static const VMStateDescription vmstate_steal_time_msr = {
+ .name = "cpu/steal_time_msr",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT64(steal_time_msr, CPUX86State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_async_pf_msr = {
.name = "cpu/async_pf_msr",
.version_id = 1,
@@ -503,6 +521,9 @@ const VMStateDescription vmstate_x86_cpu = {
.vmsd = &vmstate_pv_eoi_msr,
.needed = pv_eoi_msr_needed,
} , {
+ .vmsd = &vmstate_steal_time_msr,
+ .needed = steal_time_msr_needed,
+ } , {
.vmsd = &vmstate_fpop_ip_dp,
.needed = fpop_ip_dp_needed,
}, {
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 233f24ff41..40f891da14 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -1775,6 +1775,7 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
if (is_right) {
tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
+ tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
} else {
tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 048cc97347..d51462a015 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -495,7 +495,7 @@ QemuCocoaView *cocoaView;
if (keycode == 58 || keycode == 69) { // emulate caps lock and num lock keydown and keyup
kbd_put_keycode(keycode);
kbd_put_keycode(keycode | 0x80);
- } else if (is_graphic_console()) {
+ } else if (qemu_console_is_graphic(NULL)) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
if (modifiers_state[keycode] == 0) { // keydown
@@ -535,7 +535,7 @@ QemuCocoaView *cocoaView;
}
// handle keys for graphic console
- } else if (is_graphic_console()) {
+ } else if (qemu_console_is_graphic(NULL)) {
if (keycode & 0x80) //check bit for e0 in front
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
@@ -578,7 +578,7 @@ QemuCocoaView *cocoaView;
break;
case NSKeyUp:
keycode = cocoa_keycode_to_qemu([event keyCode]);
- if (is_graphic_console()) {
+ if (qemu_console_is_graphic(NULL)) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
@@ -1006,7 +1006,7 @@ static void cocoa_refresh(DisplayChangeListener *dcl)
[cocoaView handleEvent:event];
}
} while(event != nil);
- vga_hw_update();
+ graphic_hw_update(NULL);
}
static void cocoa_cleanup(void)
diff --git a/ui/input.c b/ui/input.c
index 9abef0cd78..ecfeb43824 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -234,13 +234,11 @@ static void free_keycodes(void)
static void release_keys(void *opaque)
{
- int i;
-
- for (i = 0; i < keycodes_size; i++) {
- if (keycodes[i] & 0x80) {
+ while (keycodes_size > 0) {
+ if (keycodes[--keycodes_size] & 0x80) {
kbd_put_keycode(0xe0);
}
- kbd_put_keycode(keycodes[i]| 0x80);
+ kbd_put_keycode(keycodes[keycodes_size] | 0x80);
}
free_keycodes();