diff options
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); } @@ -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); @@ -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(); |