diff options
83 files changed, 2365 insertions, 1764 deletions
@@ -178,7 +178,7 @@ Makefile: $(version-obj-y) $(version-lobj-y) # Build libraries libqemustub.a: $(stub-obj-y) -libqemuutil.a: $(util-obj-y) +libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o ###################################################################### @@ -215,10 +215,10 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) qapi-types.c qapi-types.h :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." -b < $<, " GEN $@") qapi-visit.c qapi-visit.h :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@") qmp-commands.h qmp-marshal.c :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") @@ -1 +1 @@ -1.5.0 +1.5.50 diff --git a/arch_init.c b/arch_init.c index 49c5dc27e6..5d32ecf23a 100644 --- a/arch_init.c +++ b/arch_init.c @@ -386,7 +386,7 @@ static void migration_bitmap_sync(void) } trace_migration_bitmap_sync_start(); - memory_global_sync_dirty_bitmap(get_system_memory()); + address_space_sync_dirty_bitmap(&address_space_memory); QTAILQ_FOREACH(block, &ram_list.blocks, next) { for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) { diff --git a/audio/audio_win_int.c b/audio/audio_win_int.c index 58690524c4..e1324056a4 100644 --- a/audio/audio_win_int.c +++ b/audio/audio_win_int.c @@ -1,7 +1,6 @@ /* public domain */ #include "qemu-common.h" -#include "audio.h" #define AUDIO_CAP "win-int" #include <windows.h> diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 00be9c91e3..007c64115a 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -25,11 +25,7 @@ #include <sys/mman.h> #include <sys/types.h> #include <sys/ioctl.h> -#ifdef __OpenBSD__ -#include <soundcard.h> -#else #include <sys/soundcard.h> -#endif #include "qemu-common.h" #include "qemu/main-loop.h" #include "qemu/host-utils.h" diff --git a/block/win32-aio.c b/block/win32-aio.c index 5d0fbbfb7d..fcb7c754da 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -25,7 +25,6 @@ #include "qemu/timer.h" #include "block/block_int.h" #include "qemu/module.h" -#include "qemu-common.h" #include "block/aio.h" #include "raw-aio.h" #include "qemu/event_notifier.h" diff --git a/blockdev.c b/blockdev.c index 7c9d8dd0ac..d1ec99af73 100644 --- a/blockdev.c +++ b/blockdev.c @@ -750,8 +750,8 @@ void do_commit(Monitor *mon, const QDict *qdict) static void blockdev_do_action(int kind, void *data, Error **errp) { - BlockdevAction action; - BlockdevActionList list; + TransactionAction action; + TransactionActionList list; action.kind = kind; action.data = data; @@ -773,27 +773,176 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, .has_mode = has_mode, .mode = mode, }; - blockdev_do_action(BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC, &snapshot, - errp); + blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC, + &snapshot, errp); } /* New and old BlockDriverState structs for group snapshots */ -typedef struct BlkTransactionStates { + +typedef struct BlkTransactionStates BlkTransactionStates; + +/* Only prepare() may fail. In a single transaction, only one of commit() or + abort() will be called, clean() will always be called if it present. */ +typedef struct BdrvActionOps { + /* Size of state struct, in bytes. */ + size_t instance_size; + /* Prepare the work, must NOT be NULL. */ + void (*prepare)(BlkTransactionStates *common, Error **errp); + /* Commit the changes, must NOT be NULL. */ + void (*commit)(BlkTransactionStates *common); + /* Abort the changes on fail, can be NULL. */ + void (*abort)(BlkTransactionStates *common); + /* Clean up resource in the end, can be NULL. */ + void (*clean)(BlkTransactionStates *common); +} BdrvActionOps; + +/* + * This structure must be arranged as first member in child type, assuming + * that compiler will also arrange it to the same address with parent instance. + * Later it will be used in free(). + */ +struct BlkTransactionStates { + TransactionAction *action; + const BdrvActionOps *ops; + QSIMPLEQ_ENTRY(BlkTransactionStates) entry; +}; + +/* external snapshot private data */ +typedef struct ExternalSnapshotStates { + BlkTransactionStates common; BlockDriverState *old_bs; BlockDriverState *new_bs; - QSIMPLEQ_ENTRY(BlkTransactionStates) entry; -} BlkTransactionStates; +} ExternalSnapshotStates; + +static void external_snapshot_prepare(BlkTransactionStates *common, + Error **errp) +{ + BlockDriver *proto_drv; + BlockDriver *drv; + int flags, ret; + Error *local_err = NULL; + const char *device; + const char *new_image_file; + const char *format = "qcow2"; + enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + ExternalSnapshotStates *states = + DO_UPCAST(ExternalSnapshotStates, common, common); + TransactionAction *action = common->action; + + /* get parameters */ + g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC); + + device = action->blockdev_snapshot_sync->device; + new_image_file = action->blockdev_snapshot_sync->snapshot_file; + if (action->blockdev_snapshot_sync->has_format) { + format = action->blockdev_snapshot_sync->format; + } + if (action->blockdev_snapshot_sync->has_mode) { + mode = action->blockdev_snapshot_sync->mode; + } + + /* start processing */ + drv = bdrv_find_format(format); + if (!drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + + states->old_bs = bdrv_find(device); + if (!states->old_bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, device); + return; + } + + if (!bdrv_is_inserted(states->old_bs)) { + error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); + return; + } + + if (bdrv_in_use(states->old_bs)) { + error_set(errp, QERR_DEVICE_IN_USE, device); + return; + } + + if (!bdrv_is_read_only(states->old_bs)) { + if (bdrv_flush(states->old_bs)) { + error_set(errp, QERR_IO_ERROR); + return; + } + } + + flags = states->old_bs->open_flags; + + proto_drv = bdrv_find_protocol(new_image_file); + if (!proto_drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; + } + + /* create new image w/backing file */ + if (mode != NEW_IMAGE_MODE_EXISTING) { + bdrv_img_create(new_image_file, format, + states->old_bs->filename, + states->old_bs->drv->format_name, + NULL, -1, flags, &local_err, false); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + return; + } + } + + /* We will manually add the backing_hd field to the bs later */ + states->new_bs = bdrv_new(""); + /* TODO Inherit bs->options or only take explicit options with an + * extended QMP command? */ + ret = bdrv_open(states->new_bs, new_image_file, NULL, + flags | BDRV_O_NO_BACKING, drv); + if (ret != 0) { + error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); + } +} + +static void external_snapshot_commit(BlkTransactionStates *common) +{ + ExternalSnapshotStates *states = + DO_UPCAST(ExternalSnapshotStates, common, common); + + /* This removes our old bs from the bdrv_states, and adds the new bs */ + bdrv_append(states->new_bs, states->old_bs); + /* We don't need (or want) to use the transactional + * bdrv_reopen_multiple() across all the entries at once, because we + * don't want to abort all of them if one of them fails the reopen */ + bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR, + NULL); +} + +static void external_snapshot_abort(BlkTransactionStates *common) +{ + ExternalSnapshotStates *states = + DO_UPCAST(ExternalSnapshotStates, common, common); + if (states->new_bs) { + bdrv_delete(states->new_bs); + } +} + +static const BdrvActionOps actions[] = { + [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] = { + .instance_size = sizeof(ExternalSnapshotStates), + .prepare = external_snapshot_prepare, + .commit = external_snapshot_commit, + .abort = external_snapshot_abort, + }, +}; /* * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail * then we do not pivot any of the devices in the group, and abandon the * snapshots */ -void qmp_transaction(BlockdevActionList *dev_list, Error **errp) +void qmp_transaction(TransactionActionList *dev_list, Error **errp) { - int ret = 0; - BlockdevActionList *dev_entry = dev_list; + TransactionActionList *dev_entry = dev_list; BlkTransactionStates *states, *next; Error *local_err = NULL; @@ -805,109 +954,29 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) /* We don't do anything in this loop that commits us to the snapshot */ while (NULL != dev_entry) { - BlockdevAction *dev_info = NULL; - BlockDriver *proto_drv; - BlockDriver *drv; - int flags; - enum NewImageMode mode; - const char *new_image_file; - const char *device; - const char *format = "qcow2"; + TransactionAction *dev_info = NULL; + const BdrvActionOps *ops; dev_info = dev_entry->value; dev_entry = dev_entry->next; - states = g_malloc0(sizeof(BlkTransactionStates)); - QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry); - - switch (dev_info->kind) { - case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC: - device = dev_info->blockdev_snapshot_sync->device; - if (!dev_info->blockdev_snapshot_sync->has_mode) { - dev_info->blockdev_snapshot_sync->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; - } - new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file; - if (dev_info->blockdev_snapshot_sync->has_format) { - format = dev_info->blockdev_snapshot_sync->format; - } - mode = dev_info->blockdev_snapshot_sync->mode; - break; - default: - abort(); - } + assert(dev_info->kind < ARRAY_SIZE(actions)); - drv = bdrv_find_format(format); - if (!drv) { - error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - goto delete_and_fail; - } - - states->old_bs = bdrv_find(device); - if (!states->old_bs) { - error_set(errp, QERR_DEVICE_NOT_FOUND, device); - goto delete_and_fail; - } - - if (!bdrv_is_inserted(states->old_bs)) { - error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); - goto delete_and_fail; - } - - if (bdrv_in_use(states->old_bs)) { - error_set(errp, QERR_DEVICE_IN_USE, device); - goto delete_and_fail; - } - - if (!bdrv_is_read_only(states->old_bs)) { - if (bdrv_flush(states->old_bs)) { - error_set(errp, QERR_IO_ERROR); - goto delete_and_fail; - } - } - - flags = states->old_bs->open_flags; - - proto_drv = bdrv_find_protocol(new_image_file); - if (!proto_drv) { - error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - goto delete_and_fail; - } - - /* create new image w/backing file */ - if (mode != NEW_IMAGE_MODE_EXISTING) { - bdrv_img_create(new_image_file, format, - states->old_bs->filename, - states->old_bs->drv->format_name, - NULL, -1, flags, &local_err, false); - if (error_is_set(&local_err)) { - error_propagate(errp, local_err); - goto delete_and_fail; - } - } + ops = &actions[dev_info->kind]; + states = g_malloc0(ops->instance_size); + states->ops = ops; + states->action = dev_info; + QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry); - /* We will manually add the backing_hd field to the bs later */ - states->new_bs = bdrv_new(""); - /* TODO Inherit bs->options or only take explicit options with an - * extended QMP command? */ - ret = bdrv_open(states->new_bs, new_image_file, NULL, - flags | BDRV_O_NO_BACKING, drv); - if (ret != 0) { - error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); + states->ops->prepare(states, &local_err); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); goto delete_and_fail; } } - - /* Now we are going to do the actual pivot. Everything up to this point - * is reversible, but we are committed at this point */ QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { - /* This removes our old bs from the bdrv_states, and adds the new bs */ - bdrv_append(states->new_bs, states->old_bs); - /* We don't need (or want) to use the transactional - * bdrv_reopen_multiple() across all the entries at once, because we - * don't want to abort all of them if one of them fails the reopen */ - bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR, - NULL); + states->ops->commit(states); } /* success */ @@ -919,12 +988,15 @@ delete_and_fail: * the original bs for all images */ QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { - if (states->new_bs) { - bdrv_delete(states->new_bs); + if (states->ops->abort) { + states->ops->abort(states); } } exit: QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) { + if (states->ops->clean) { + states->ops->clean(states); + } g_free(states); } } @@ -468,9 +468,8 @@ NetBSD) OpenBSD) bsd="yes" make="${MAKE-gmake}" - audio_drv_list="oss" - audio_possible_drivers="oss sdl esd" - oss_lib="-lossaudio" + audio_drv_list="sdl" + audio_possible_drivers="sdl esd" ;; Darwin) bsd="yes" @@ -187,19 +187,15 @@ MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index) PhysPageEntry lp = d->phys_map; PhysPageEntry *p; int i; - uint16_t s_index = phys_section_unassigned; for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) { if (lp.ptr == PHYS_MAP_NODE_NIL) { - goto not_found; + return &phys_sections[phys_section_unassigned]; } p = phys_map_nodes[lp.ptr]; lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)]; } - - s_index = lp.ptr; -not_found: - return &phys_sections[s_index]; + return &phys_sections[lp.ptr]; } bool memory_region_is_unassigned(MemoryRegion *mr) @@ -639,12 +635,6 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, iotlb |= phys_section_rom; } } else { - /* IO handlers are currently passed a physical address. - It would be nice to pass an offset from the base address - of that region. This would avoid having to special case RAM, - and avoid full address decoding in every device. - We can't use the high bits of pd for this because - IO_MEM_ROMD uses these as a ram address. */ iotlb = section - phys_sections; iotlb += memory_region_section_addr(section, paddr); } @@ -719,6 +709,12 @@ static void destroy_all_mappings(AddressSpaceDispatch *d) static uint16_t phys_section_add(MemoryRegionSection *section) { + /* The physical section number is ORed with a page-aligned + * pointer to produce the iotlb entries. Thus it should + * never overflow into the page-aligned value. + */ + assert(phys_sections_nb < TARGET_PAGE_SIZE); + if (phys_sections_nb == phys_sections_nb_alloc) { phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16); phys_sections = g_renew(MemoryRegionSection, phys_sections, @@ -775,10 +771,21 @@ static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *sec section_index); } +QEMU_BUILD_BUG_ON(TARGET_PHYS_ADDR_SPACE_BITS > MAX_PHYS_ADDR_SPACE_BITS) + +static MemoryRegionSection limit(MemoryRegionSection section) +{ + section.size = MIN(section.offset_within_address_space + section.size, + MAX_PHYS_ADDR + 1) + - section.offset_within_address_space; + + return section; +} + static void mem_add(MemoryListener *listener, MemoryRegionSection *section) { AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); - MemoryRegionSection now = *section, remain = *section; + MemoryRegionSection now = limit(*section), remain = limit(*section); if ((now.offset_within_address_space & ~TARGET_PAGE_MASK) || (now.size < TARGET_PAGE_SIZE)) { @@ -1340,11 +1347,6 @@ static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size) } } -void qemu_put_ram_ptr(void *addr) -{ - trace_qemu_put_ram_ptr(addr); -} - int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) { RAMBlock *block; @@ -1934,7 +1936,6 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); invalidate_and_set_dirty(addr1, l); - qemu_put_ram_ptr(ptr); } } else { if (!(memory_region_is_ram(section->mr) || @@ -1964,7 +1965,6 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, + memory_region_section_addr(section, addr)); memcpy(buf, ptr, l); - qemu_put_ram_ptr(ptr); } } len -= l; @@ -2026,7 +2026,6 @@ void cpu_physical_memory_write_rom(hwaddr addr, ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); invalidate_and_set_dirty(addr1, l); - qemu_put_ram_ptr(ptr); } len -= l; buf += l; @@ -2404,33 +2403,6 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val) } } -void stq_phys_notdirty(hwaddr addr, uint64_t val) -{ - uint8_t *ptr; - MemoryRegionSection *section; - - section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); - - if (!memory_region_is_ram(section->mr) || section->readonly) { - addr = memory_region_section_addr(section, addr); - if (memory_region_is_ram(section->mr)) { - section = &phys_sections[phys_section_rom]; - } -#ifdef TARGET_WORDS_BIGENDIAN - io_mem_write(section->mr, addr, val >> 32, 4); - io_mem_write(section->mr, addr + 4, (uint32_t)val, 4); -#else - io_mem_write(section->mr, addr, (uint32_t)val, 4); - io_mem_write(section->mr, addr + 4, val >> 32, 4); -#endif - } else { - ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr) - & TARGET_PAGE_MASK) - + memory_region_section_addr(section, addr)); - stq_p(ptr, val); - } -} - /* warning: addr must be aligned */ static inline void stl_phys_internal(hwaddr addr, uint32_t val, enum device_endian endian) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 0fd9465cfa..4405dbd3bd 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -24,7 +24,6 @@ #include "net/net.h" #include "sysemu/sysemu.h" #include "hw/boards.h" -#include "hw/sysbus.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index de06dfd7d2..c5d88a7841 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -12,7 +12,6 @@ #include "hw/sysbus.h" #include "hw/hw.h" #include "hw/i2c/i2c.h" -#include "hw/sysbus.h" #include "audio/audio.h" #define MP_AUDIO_SIZE 0x00001000 diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 3ff20e0c6f..63d7c9951f 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -105,7 +105,7 @@ static void pflash_timer (void *opaque) DPRINTF("%s: command %02x done\n", __func__, pfl->cmd); /* Reset flash */ pfl->status ^= 0x80; - memory_region_rom_device_set_readable(&pfl->mem, true); + memory_region_rom_device_set_romd(&pfl->mem, true); pfl->wcycle = 0; pfl->cmd = 0; } @@ -281,7 +281,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset, if (!pfl->wcycle) { /* Set the device in I/O access mode */ - memory_region_rom_device_set_readable(&pfl->mem, false); + memory_region_rom_device_set_romd(&pfl->mem, false); } switch (pfl->wcycle) { @@ -458,7 +458,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset, "\n", __func__, offset, pfl->wcycle, pfl->cmd, value); reset_flash: - memory_region_rom_device_set_readable(&pfl->mem, true); + memory_region_rom_device_set_romd(&pfl->mem, true); pfl->wcycle = 0; pfl->cmd = 0; diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 9a7fa707ca..5f25246926 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -111,7 +111,7 @@ static void pflash_setup_mappings(pflash_t *pfl) static void pflash_register_memory(pflash_t *pfl, int rom_mode) { - memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode); + memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode); pfl->rom_mode = rom_mode; } diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index c1e08ec1a0..ff855904ba 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -1026,6 +1026,21 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev) } } +static void assigned_dev_update_msi_msg(PCIDevice *pci_dev) +{ + AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); + uint8_t ctrl_byte = pci_get_byte(pci_dev->config + pci_dev->msi_cap + + PCI_MSI_FLAGS); + + if (assigned_dev->assigned_irq_type != ASSIGNED_IRQ_MSI || + !(ctrl_byte & PCI_MSI_FLAGS_ENABLE)) { + return; + } + + kvm_irqchip_update_msi_route(kvm_state, assigned_dev->msi_virq[0], + msi_get_message(pci_dev, 0)); +} + static bool assigned_dev_msix_masked(MSIXTableEntry *entry) { return (entry->ctrl & cpu_to_le32(0x1)) != 0; @@ -1201,6 +1216,9 @@ static void assigned_dev_pci_write_config(PCIDevice *pci_dev, uint32_t address, if (range_covers_byte(address, len, pci_dev->msi_cap + PCI_MSI_FLAGS)) { assigned_dev_update_msi(pci_dev); + } else if (ranges_overlap(address, len, /* 32bit MSI only */ + pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, 6)) { + assigned_dev_update_msi_msg(pci_dev); } } if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) { diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 718d97ae8a..3e68d2eba8 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -7,7 +7,7 @@ common-obj-$(CONFIG_ETRAXFS) += etraxfs_pic.o common-obj-$(CONFIG_IMX) += imx_avic.o common-obj-$(CONFIG_LM32) += lm32_pic.o common-obj-$(CONFIG_REALVIEW) += realview_gic.o -common-obj-$(CONFIG_SLAVIO) += sbi.o slavio_intctl.o sun4c_intctl.o +common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o common-obj-$(CONFIG_IOAPIC) += ioapic_common.o common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o diff --git a/hw/intc/sbi.c b/hw/intc/sbi.c deleted file mode 100644 index 8795749de8..0000000000 --- a/hw/intc/sbi.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * QEMU Sparc SBI interrupt controller emulation - * - * Based on slavio_intctl, copyright (c) 2003-2005 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw/sysbus.h" - -//#define DEBUG_IRQ - -#ifdef DEBUG_IRQ -#define DPRINTF(fmt, ...) \ - do { printf("IRQ: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) -#endif - -#define MAX_CPUS 16 - -#define SBI_NREGS 16 - -typedef struct SBIState { - SysBusDevice busdev; - MemoryRegion iomem; - uint32_t regs[SBI_NREGS]; - uint32_t intreg_pending[MAX_CPUS]; - qemu_irq cpu_irqs[MAX_CPUS]; - uint32_t pil_out[MAX_CPUS]; -} SBIState; - -#define SBI_SIZE (SBI_NREGS * 4) - -static void sbi_set_irq(void *opaque, int irq, int level) -{ -} - -static uint64_t sbi_mem_read(void *opaque, hwaddr addr, - unsigned size) -{ - SBIState *s = opaque; - uint32_t saddr, ret; - - saddr = addr >> 2; - switch (saddr) { - default: - ret = s->regs[saddr]; - break; - } - DPRINTF("read system reg 0x" TARGET_FMT_plx " = %x\n", addr, ret); - - return ret; -} - -static void sbi_mem_write(void *opaque, hwaddr addr, - uint64_t val, unsigned dize) -{ - SBIState *s = opaque; - uint32_t saddr; - - saddr = addr >> 2; - DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, (int)val); - switch (saddr) { - default: - s->regs[saddr] = val; - break; - } -} - -static const MemoryRegionOps sbi_mem_ops = { - .read = sbi_mem_read, - .write = sbi_mem_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static const VMStateDescription vmstate_sbi = { - .name ="sbi", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_UINT32_ARRAY(intreg_pending, SBIState, MAX_CPUS), - VMSTATE_END_OF_LIST() - } -}; - -static void sbi_reset(DeviceState *d) -{ - SBIState *s = container_of(d, SBIState, busdev.qdev); - unsigned int i; - - for (i = 0; i < MAX_CPUS; i++) { - s->intreg_pending[i] = 0; - } -} - -static int sbi_init1(SysBusDevice *dev) -{ - SBIState *s = FROM_SYSBUS(SBIState, dev); - unsigned int i; - - qdev_init_gpio_in(&dev->qdev, sbi_set_irq, 32 + MAX_CPUS); - for (i = 0; i < MAX_CPUS; i++) { - sysbus_init_irq(dev, &s->cpu_irqs[i]); - } - - memory_region_init_io(&s->iomem, &sbi_mem_ops, s, "sbi", SBI_SIZE); - sysbus_init_mmio(dev, &s->iomem); - - return 0; -} - -static void sbi_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = sbi_init1; - dc->reset = sbi_reset; - dc->vmsd = &vmstate_sbi; -} - -static const TypeInfo sbi_info = { - .name = "sbi", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SBIState), - .class_init = sbi_class_init, -}; - -static void sbi_register_types(void) -{ - type_register_static(&sbi_info); -} - -type_init(sbi_register_types) diff --git a/hw/intc/sun4c_intctl.c b/hw/intc/sun4c_intctl.c deleted file mode 100644 index 1096375670..0000000000 --- a/hw/intc/sun4c_intctl.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * QEMU Sparc Sun4c interrupt controller emulation - * - * Based on slavio_intctl, copyright (c) 2003-2005 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw/hw.h" -#include "hw/sparc/sun4m.h" -#include "monitor/monitor.h" -#include "hw/sysbus.h" - -//#define DEBUG_IRQ_COUNT -//#define DEBUG_IRQ - -#ifdef DEBUG_IRQ -#define DPRINTF(fmt, ...) \ - do { printf("IRQ: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) -#endif - -/* - * Registers of interrupt controller in sun4c. - * - */ - -#define MAX_PILS 16 - -typedef struct Sun4c_INTCTLState { - SysBusDevice busdev; - MemoryRegion iomem; -#ifdef DEBUG_IRQ_COUNT - uint64_t irq_count; -#endif - qemu_irq cpu_irqs[MAX_PILS]; - const uint32_t *intbit_to_level; - uint32_t pil_out; - uint8_t reg; - uint8_t pending; -} Sun4c_INTCTLState; - -#define INTCTL_SIZE 1 - -static void sun4c_check_interrupts(void *opaque); - -static uint64_t sun4c_intctl_mem_read(void *opaque, hwaddr addr, - unsigned size) -{ - Sun4c_INTCTLState *s = opaque; - uint32_t ret; - - ret = s->reg; - DPRINTF("read reg 0x" TARGET_FMT_plx " = %x\n", addr, ret); - - return ret; -} - -static void sun4c_intctl_mem_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - Sun4c_INTCTLState *s = opaque; - - DPRINTF("write reg 0x" TARGET_FMT_plx " = %x\n", addr, (unsigned)val); - val &= 0xbf; - s->reg = val; - sun4c_check_interrupts(s); -} - -static const MemoryRegionOps sun4c_intctl_mem_ops = { - .read = sun4c_intctl_mem_read, - .write = sun4c_intctl_mem_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 1, - }, -}; - -static const uint32_t intbit_to_level[] = { 0, 1, 4, 6, 8, 10, 0, 14, }; - -static void sun4c_check_interrupts(void *opaque) -{ - Sun4c_INTCTLState *s = opaque; - uint32_t pil_pending; - unsigned int i; - - pil_pending = 0; - if (s->pending && !(s->reg & 0x80000000)) { - for (i = 0; i < 8; i++) { - if (s->pending & (1 << i)) - pil_pending |= 1 << intbit_to_level[i]; - } - } - - for (i = 0; i < MAX_PILS; i++) { - if (pil_pending & (1 << i)) { - if (!(s->pil_out & (1 << i))) - qemu_irq_raise(s->cpu_irqs[i]); - } else { - if (s->pil_out & (1 << i)) - qemu_irq_lower(s->cpu_irqs[i]); - } - } - s->pil_out = pil_pending; -} - -/* - * "irq" here is the bit number in the system interrupt register - */ -static void sun4c_set_irq(void *opaque, int irq, int level) -{ - Sun4c_INTCTLState *s = opaque; - uint32_t mask = 1 << irq; - uint32_t pil = intbit_to_level[irq]; - - DPRINTF("Set irq %d -> pil %d level %d\n", irq, pil, - level); - if (pil > 0) { - if (level) { -#ifdef DEBUG_IRQ_COUNT - s->irq_count++; -#endif - s->pending |= mask; - } else { - s->pending &= ~mask; - } - sun4c_check_interrupts(s); - } -} - -static const VMStateDescription vmstate_sun4c_intctl = { - .name ="sun4c_intctl", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_UINT8(reg, Sun4c_INTCTLState), - VMSTATE_UINT8(pending, Sun4c_INTCTLState), - VMSTATE_END_OF_LIST() - } -}; - -static void sun4c_intctl_reset(DeviceState *d) -{ - Sun4c_INTCTLState *s = container_of(d, Sun4c_INTCTLState, busdev.qdev); - - s->reg = 1; - s->pending = 0; -} - -static int sun4c_intctl_init1(SysBusDevice *dev) -{ - Sun4c_INTCTLState *s = FROM_SYSBUS(Sun4c_INTCTLState, dev); - unsigned int i; - - memory_region_init_io(&s->iomem, &sun4c_intctl_mem_ops, s, - "intctl", INTCTL_SIZE); - sysbus_init_mmio(dev, &s->iomem); - qdev_init_gpio_in(&dev->qdev, sun4c_set_irq, 8); - - for (i = 0; i < MAX_PILS; i++) { - sysbus_init_irq(dev, &s->cpu_irqs[i]); - } - - return 0; -} - -static void sun4c_intctl_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = sun4c_intctl_init1; - dc->reset = sun4c_intctl_reset; - dc->vmsd = &vmstate_sun4c_intctl; -} - -static const TypeInfo sun4c_intctl_info = { - .name = "sun4c_intctl", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(Sun4c_INTCTLState), - .class_init = sun4c_intctl_class_init, -}; - -static void sun4c_intctl_register_types(void) -{ - type_register_static(&sun4c_intctl_info); -} - -type_init(sun4c_intctl_register_types) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 9d521ccb19..5033d51224 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -37,7 +37,6 @@ #include "sysemu/char.h" #include "sysemu/sysemu.h" #include "sysemu/arch_init.h" -#include "hw/boards.h" #include "qemu/log.h" #include "hw/mips/bios.h" #include "hw/ide.h" diff --git a/hw/misc/lm32_sys.c b/hw/misc/lm32_sys.c index 33a3b80ce7..aeaf2b7b7b 100644 --- a/hw/misc/lm32_sys.c +++ b/hw/misc/lm32_sys.c @@ -34,7 +34,6 @@ #include "qemu/log.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" -#include "qemu/log.h" enum { R_CTRL = 0, diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 9369507422..7993f9f5b9 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -2575,6 +2575,9 @@ static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val) /* this value is off by 16 */ s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize); + /* more buffer space may be available so try to receive */ + qemu_flush_queued_packets(qemu_get_queue(s->nic)); + DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", s->RxBufferSize, s->RxBufAddr, s->RxBufPtr); } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index bed0822f0a..1ea95564a5 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -359,6 +359,34 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev) return features; } +static void virtio_net_apply_guest_offloads(VirtIONet *n) +{ + tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer, + !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)), + !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)), + !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)), + !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)), + !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO))); +} + +static uint64_t virtio_net_guest_offloads_by_features(uint32_t features) +{ + static const uint64_t guest_offloads_mask = + (1ULL << VIRTIO_NET_F_GUEST_CSUM) | + (1ULL << VIRTIO_NET_F_GUEST_TSO4) | + (1ULL << VIRTIO_NET_F_GUEST_TSO6) | + (1ULL << VIRTIO_NET_F_GUEST_ECN) | + (1ULL << VIRTIO_NET_F_GUEST_UFO); + + return guest_offloads_mask & features; +} + +static inline uint64_t virtio_net_supported_guest_offloads(VirtIONet *n) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(n); + return virtio_net_guest_offloads_by_features(vdev->guest_features); +} + static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) { VirtIONet *n = VIRTIO_NET(vdev); @@ -369,12 +397,9 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF))); if (n->has_vnet_hdr) { - tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer, - (features >> VIRTIO_NET_F_GUEST_CSUM) & 1, - (features >> VIRTIO_NET_F_GUEST_TSO4) & 1, - (features >> VIRTIO_NET_F_GUEST_TSO6) & 1, - (features >> VIRTIO_NET_F_GUEST_ECN) & 1, - (features >> VIRTIO_NET_F_GUEST_UFO) & 1); + n->curr_guest_offloads = + virtio_net_guest_offloads_by_features(features); + virtio_net_apply_guest_offloads(n); } for (i = 0; i < n->max_queues; i++) { @@ -420,6 +445,43 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, return VIRTIO_NET_OK; } +static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd, + struct iovec *iov, unsigned int iov_cnt) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(n); + uint64_t offloads; + size_t s; + + if (!((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features)) { + return VIRTIO_NET_ERR; + } + + s = iov_to_buf(iov, iov_cnt, 0, &offloads, sizeof(offloads)); + if (s != sizeof(offloads)) { + return VIRTIO_NET_ERR; + } + + if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) { + uint64_t supported_offloads; + + if (!n->has_vnet_hdr) { + return VIRTIO_NET_ERR; + } + + supported_offloads = virtio_net_supported_guest_offloads(n); + if (offloads & ~supported_offloads) { + return VIRTIO_NET_ERR; + } + + n->curr_guest_offloads = offloads; + virtio_net_apply_guest_offloads(n); + + return VIRTIO_NET_OK; + } else { + return VIRTIO_NET_ERR; + } +} + static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, struct iovec *iov, unsigned int iov_cnt) { @@ -590,6 +652,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt); } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) { status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt); + } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) { + status = virtio_net_handle_offloads(n, ctrl.cmd, iov, iov_cnt); } s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status)); @@ -1110,6 +1174,10 @@ static void virtio_net_save(QEMUFile *f, void *opaque) qemu_put_be32(f, n->vqs[i].tx_waiting); } } + + if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) { + qemu_put_be64(f, n->curr_guest_offloads); + } } static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) @@ -1167,15 +1235,6 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) error_report("virtio-net: saved image requires vnet_hdr=on"); return -1; } - - if (n->has_vnet_hdr) { - tap_set_offload(qemu_get_queue(n->nic)->peer, - (vdev->guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1, - (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1, - (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO6) & 1, - (vdev->guest_features >> VIRTIO_NET_F_GUEST_ECN) & 1, - (vdev->guest_features >> VIRTIO_NET_F_GUEST_UFO) & 1); - } } if (version_id >= 9) { @@ -1209,6 +1268,16 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) } } + if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) { + n->curr_guest_offloads = qemu_get_be64(f); + } else { + n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); + } + + if (peer_has_vnet_hdr(n)) { + virtio_net_apply_guest_offloads(n); + } + virtio_net_set_queues(n); /* Find the first multicast entry in the saved MAC filter */ diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 1a7e49c132..479113bd81 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -54,7 +54,7 @@ struct FWCfgState { #define JPG_FILE 0 #define BMP_FILE 1 -static char *read_splashfile(char *filename, size_t *file_sizep, +static char *read_splashfile(char *filename, gsize *file_sizep, int *file_typep) { GError *err = NULL; @@ -112,7 +112,7 @@ static void fw_cfg_bootsplash(FWCfgState *s) const char *boot_splash_filename = NULL; char *p; char *filename, *file_data; - size_t file_size; + gsize file_size; int file_type; const char *temp; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index d5257ed4c5..bb3879bd88 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1959,8 +1959,6 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) pci_patch_ids(pdev, ptr, size); } - qemu_put_ram_ptr(ptr); - pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom); return 0; diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c96ac8131f..218ea23da8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -43,8 +43,6 @@ #include "hw/ppc/xics.h" #include "hw/pci/msi.h" -#include "sysemu/kvm.h" -#include "kvm_ppc.h" #include "hw/pci/pci.h" #include "exec/address-spaces.h" diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index f518aee216..8f0b7e8076 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1,6 +1,5 @@ #include "sysemu/sysemu.h" #include "cpu.h" -#include "sysemu/sysemu.h" #include "helper_regs.h" #include "hw/ppc/spapr.h" #include "mmu-hash64.h" diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 4934a815ce..fe6550ca54 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -711,7 +711,6 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) ptr = memory_region_get_ram_ptr(&s->dev.rom); memcpy(biosver, ptr + 0x41, 31); - qemu_put_ram_ptr(ptr); memcpy(info.image_component[1].name, "BIOS", 4); memcpy(info.image_component[1].version, biosver, strlen((const char *)biosver)); diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 635115f097..884088150b 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -55,18 +55,6 @@ * SPARCstation 20/xx, SPARCserver 20 * SPARCstation 4 * - * Sun4d architecture was used in the following machines: - * - * SPARCcenter 2000 - * SPARCserver 1000 - * - * Sun4c architecture was used in the following machines: - * SPARCstation 1/1+, SPARCserver 1/1+ - * SPARCstation SLC - * SPARCstation IPC - * SPARCstation ELC - * SPARCstation IPX - * * See for example: http://www.sunhelp.org/faq/sunref1.html */ @@ -104,36 +92,6 @@ struct sun4m_hwdef { uint8_t nvram_machine_id; }; -#define MAX_IOUNITS 5 - -struct sun4d_hwdef { - hwaddr iounit_bases[MAX_IOUNITS], slavio_base; - hwaddr counter_base, nvram_base, ms_kb_base; - hwaddr serial_base; - hwaddr espdma_base, esp_base; - hwaddr ledma_base, le_base; - hwaddr tcx_base; - hwaddr sbi_base; - uint64_t max_mem; - const char * const default_cpu_model; - uint32_t iounit_version; - uint16_t machine_id; - uint8_t nvram_machine_id; -}; - -struct sun4c_hwdef { - hwaddr iommu_base, slavio_base; - hwaddr intctl_base, counter_base, nvram_base, ms_kb_base; - hwaddr serial_base, fd_base; - hwaddr idreg_base, dma_base, esp_base, le_base; - hwaddr tcx_base, aux1_base; - uint64_t max_mem; - const char * const default_cpu_model; - uint32_t iommu_version; - uint16_t machine_id; - uint8_t nvram_machine_id; -}; - int DMA_get_channel_mode (int nchan) { return 0; @@ -1052,7 +1010,6 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, } enum { - ss2_id = 0, ss5_id = 32, vger_id, lx_id, @@ -1062,8 +1019,6 @@ enum { ss10_id = 64, ss20_id, ss600mp_id, - ss1000_id = 96, - ss2000_id, }; static const struct sun4m_hwdef sun4m_hwdefs[] = { @@ -1504,417 +1459,6 @@ static QEMUMachine sbook_machine = { DEFAULT_MACHINE_OPTIONS, }; -static const struct sun4d_hwdef sun4d_hwdefs[] = { - /* SS-1000 */ - { - .iounit_bases = { - 0xfe0200000ULL, - 0xfe1200000ULL, - 0xfe2200000ULL, - 0xfe3200000ULL, - -1, - }, - .tcx_base = 0x820000000ULL, - .slavio_base = 0xf00000000ULL, - .ms_kb_base = 0xf00240000ULL, - .serial_base = 0xf00200000ULL, - .nvram_base = 0xf00280000ULL, - .counter_base = 0xf00300000ULL, - .espdma_base = 0x800081000ULL, - .esp_base = 0x800080000ULL, - .ledma_base = 0x800040000ULL, - .le_base = 0x800060000ULL, - .sbi_base = 0xf02800000ULL, - .nvram_machine_id = 0x80, - .machine_id = ss1000_id, - .iounit_version = 0x03000000, - .max_mem = 0xf00000000ULL, - .default_cpu_model = "TI SuperSparc II", - }, - /* SS-2000 */ - { - .iounit_bases = { - 0xfe0200000ULL, - 0xfe1200000ULL, - 0xfe2200000ULL, - 0xfe3200000ULL, - 0xfe4200000ULL, - }, - .tcx_base = 0x820000000ULL, - .slavio_base = 0xf00000000ULL, - .ms_kb_base = 0xf00240000ULL, - .serial_base = 0xf00200000ULL, - .nvram_base = 0xf00280000ULL, - .counter_base = 0xf00300000ULL, - .espdma_base = 0x800081000ULL, - .esp_base = 0x800080000ULL, - .ledma_base = 0x800040000ULL, - .le_base = 0x800060000ULL, - .sbi_base = 0xf02800000ULL, - .nvram_machine_id = 0x80, - .machine_id = ss2000_id, - .iounit_version = 0x03000000, - .max_mem = 0xf00000000ULL, - .default_cpu_model = "TI SuperSparc II", - }, -}; - -static DeviceState *sbi_init(hwaddr addr, qemu_irq **parent_irq) -{ - DeviceState *dev; - SysBusDevice *s; - unsigned int i; - - dev = qdev_create(NULL, "sbi"); - qdev_init_nofail(dev); - - s = SYS_BUS_DEVICE(dev); - - for (i = 0; i < MAX_CPUS; i++) { - sysbus_connect_irq(s, i, *parent_irq[i]); - } - - sysbus_mmio_map(s, 0, addr); - - return dev; -} - -static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) -{ - unsigned int i; - void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram; - qemu_irq *cpu_irqs[MAX_CPUS], sbi_irq[32], sbi_cpu_irq[MAX_CPUS], - espdma_irq, ledma_irq; - qemu_irq esp_reset, dma_enable; - unsigned long kernel_size; - void *fw_cfg; - DeviceState *dev; - - /* init CPUs */ - if (!cpu_model) - cpu_model = hwdef->default_cpu_model; - - for(i = 0; i < smp_cpus; i++) { - cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]); - } - - for (i = smp_cpus; i < MAX_CPUS; i++) - cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS); - - /* set up devices */ - ram_init(0, RAM_size, hwdef->max_mem); - - prom_init(hwdef->slavio_base, bios_name); - - dev = sbi_init(hwdef->sbi_base, cpu_irqs); - - for (i = 0; i < 32; i++) { - sbi_irq[i] = qdev_get_gpio_in(dev, i); - } - for (i = 0; i < MAX_CPUS; i++) { - sbi_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i); - } - - for (i = 0; i < MAX_IOUNITS; i++) - if (hwdef->iounit_bases[i] != (hwaddr)-1) - iounits[i] = iommu_init(hwdef->iounit_bases[i], - hwdef->iounit_version, - sbi_irq[0]); - - espdma = sparc32_dma_init(hwdef->espdma_base, sbi_irq[3], - iounits[0], &espdma_irq, 0); - - /* should be lebuffer instead */ - ledma = sparc32_dma_init(hwdef->ledma_base, sbi_irq[4], - iounits[0], &ledma_irq, 0); - - if (graphic_depth != 8 && graphic_depth != 24) { - fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth); - exit (1); - } - tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height, - graphic_depth); - - lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq); - - nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0, 0x2000, 8); - - slavio_timer_init_all(hwdef->counter_base, sbi_irq[10], sbi_cpu_irq, smp_cpus); - - slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[12], - display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1); - /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device - Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ - escc_init(hwdef->serial_base, sbi_irq[12], sbi_irq[12], - serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); - - if (drive_get_max_bus(IF_SCSI) > 0) { - fprintf(stderr, "qemu: too many SCSI bus\n"); - exit(1); - } - - esp_init(hwdef->esp_base, 2, - espdma_memory_read, espdma_memory_write, - espdma, espdma_irq, &esp_reset, &dma_enable); - - qdev_connect_gpio_out(espdma, 0, esp_reset); - qdev_connect_gpio_out(espdma, 1, dma_enable); - - kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, - RAM_size); - - nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, - boot_device, RAM_size, kernel_size, graphic_width, - graphic_height, graphic_depth, hwdef->nvram_machine_id, - "Sun4d"); - - fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); - fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); - fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); - fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth); - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR); - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); - if (kernel_cmdline) { - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR); - pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline); - fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline); - } else { - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); - } - fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR); - fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used - fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]); - qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); -} - -/* SPARCserver 1000 hardware initialisation */ -static void ss1000_init(QEMUMachineInitArgs *args) -{ - ram_addr_t RAM_size = args->ram_size; - const char *cpu_model = args->cpu_model; - const char *kernel_filename = args->kernel_filename; - const char *kernel_cmdline = args->kernel_cmdline; - const char *initrd_filename = args->initrd_filename; - const char *boot_device = args->boot_device; - sun4d_hw_init(&sun4d_hwdefs[0], RAM_size, boot_device, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model); -} - -/* SPARCcenter 2000 hardware initialisation */ -static void ss2000_init(QEMUMachineInitArgs *args) -{ - ram_addr_t RAM_size = args->ram_size; - const char *cpu_model = args->cpu_model; - const char *kernel_filename = args->kernel_filename; - const char *kernel_cmdline = args->kernel_cmdline; - const char *initrd_filename = args->initrd_filename; - const char *boot_device = args->boot_device; - sun4d_hw_init(&sun4d_hwdefs[1], RAM_size, boot_device, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model); -} - -static QEMUMachine ss1000_machine = { - .name = "SS-1000", - .desc = "Sun4d platform, SPARCserver 1000", - .init = ss1000_init, - .block_default_type = IF_SCSI, - .max_cpus = 8, - DEFAULT_MACHINE_OPTIONS, -}; - -static QEMUMachine ss2000_machine = { - .name = "SS-2000", - .desc = "Sun4d platform, SPARCcenter 2000", - .init = ss2000_init, - .block_default_type = IF_SCSI, - .max_cpus = 20, - DEFAULT_MACHINE_OPTIONS, -}; - -static const struct sun4c_hwdef sun4c_hwdefs[] = { - /* SS-2 */ - { - .iommu_base = 0xf8000000, - .tcx_base = 0xfe000000, - .slavio_base = 0xf6000000, - .intctl_base = 0xf5000000, - .counter_base = 0xf3000000, - .ms_kb_base = 0xf0000000, - .serial_base = 0xf1000000, - .nvram_base = 0xf2000000, - .fd_base = 0xf7200000, - .dma_base = 0xf8400000, - .esp_base = 0xf8800000, - .le_base = 0xf8c00000, - .aux1_base = 0xf7400003, - .nvram_machine_id = 0x55, - .machine_id = ss2_id, - .max_mem = 0x10000000, - .default_cpu_model = "Cypress CY7C601", - }, -}; - -static DeviceState *sun4c_intctl_init(hwaddr addr, - qemu_irq *parent_irq) -{ - DeviceState *dev; - SysBusDevice *s; - unsigned int i; - - dev = qdev_create(NULL, "sun4c_intctl"); - qdev_init_nofail(dev); - - s = SYS_BUS_DEVICE(dev); - - for (i = 0; i < MAX_PILS; i++) { - sysbus_connect_irq(s, i, parent_irq[i]); - } - sysbus_mmio_map(s, 0, addr); - - return dev; -} - -static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) -{ - void *iommu, *espdma, *ledma, *nvram; - qemu_irq *cpu_irqs, slavio_irq[8], espdma_irq, ledma_irq; - qemu_irq esp_reset, dma_enable; - qemu_irq fdc_tc; - unsigned long kernel_size; - DriveInfo *fd[MAX_FD]; - void *fw_cfg; - DeviceState *dev; - unsigned int i; - - /* init CPU */ - if (!cpu_model) - cpu_model = hwdef->default_cpu_model; - - cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs); - - /* set up devices */ - ram_init(0, RAM_size, hwdef->max_mem); - - prom_init(hwdef->slavio_base, bios_name); - - dev = sun4c_intctl_init(hwdef->intctl_base, cpu_irqs); - - for (i = 0; i < 8; i++) { - slavio_irq[i] = qdev_get_gpio_in(dev, i); - } - - iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version, - slavio_irq[1]); - - espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[2], - iommu, &espdma_irq, 0); - - ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, - slavio_irq[3], iommu, &ledma_irq, 1); - - if (graphic_depth != 8 && graphic_depth != 24) { - fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth); - exit (1); - } - tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height, - graphic_depth); - - lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq); - - nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x800, 2); - - slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[1], - display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1); - /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device - Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ - escc_init(hwdef->serial_base, slavio_irq[1], - slavio_irq[1], serial_hds[0], serial_hds[1], - ESCC_CLOCK, 1); - - if (hwdef->fd_base != (hwaddr)-1) { - /* there is zero or one floppy drive */ - memset(fd, 0, sizeof(fd)); - fd[0] = drive_get(IF_FLOPPY, 0, 0); - sun4m_fdctrl_init(slavio_irq[1], hwdef->fd_base, fd, - &fdc_tc); - } else { - fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1); - } - - slavio_misc_init(0, hwdef->aux1_base, 0, slavio_irq[1], fdc_tc); - - if (drive_get_max_bus(IF_SCSI) > 0) { - fprintf(stderr, "qemu: too many SCSI bus\n"); - exit(1); - } - - esp_init(hwdef->esp_base, 2, - espdma_memory_read, espdma_memory_write, - espdma, espdma_irq, &esp_reset, &dma_enable); - - qdev_connect_gpio_out(espdma, 0, esp_reset); - qdev_connect_gpio_out(espdma, 1, dma_enable); - - kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, - RAM_size); - - nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, - boot_device, RAM_size, kernel_size, graphic_width, - graphic_height, graphic_depth, hwdef->nvram_machine_id, - "Sun4c"); - - fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2); - fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); - fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); - fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth); - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR); - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); - if (kernel_cmdline) { - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR); - pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline); - fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline); - } else { - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); - } - fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR); - fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used - fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]); - qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); -} - -/* SPARCstation 2 hardware initialisation */ -static void ss2_init(QEMUMachineInitArgs *args) -{ - ram_addr_t RAM_size = args->ram_size; - const char *cpu_model = args->cpu_model; - const char *kernel_filename = args->kernel_filename; - const char *kernel_cmdline = args->kernel_cmdline; - const char *initrd_filename = args->initrd_filename; - const char *boot_device = args->boot_device; - sun4c_hw_init(&sun4c_hwdefs[0], RAM_size, boot_device, kernel_filename, - kernel_cmdline, initrd_filename, cpu_model); -} - -static QEMUMachine ss2_machine = { - .name = "SS-2", - .desc = "Sun4c platform, SPARCstation 2", - .init = ss2_init, - .block_default_type = IF_SCSI, - DEFAULT_MACHINE_OPTIONS, -}; - static void sun4m_register_types(void) { type_register_static(&idreg_info); @@ -1923,7 +1467,7 @@ static void sun4m_register_types(void) type_register_static(&ram_info); } -static void ss2_machine_init(void) +static void sun4m_machine_init(void) { qemu_register_machine(&ss5_machine); qemu_register_machine(&ss10_machine); @@ -1934,10 +1478,7 @@ static void ss2_machine_init(void) qemu_register_machine(&ss4_machine); qemu_register_machine(&scls_machine); qemu_register_machine(&sbook_machine); - qemu_register_machine(&ss1000_machine); - qemu_register_machine(&ss2000_machine); - qemu_register_machine(&ss2_machine); } type_init(sun4m_register_types) -machine_init(ss2_machine_init); +machine_init(sun4m_machine_init); diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c index bceee44cb2..3ac77f9262 100644 --- a/hw/timer/exynos4210_rtc.c +++ b/hw/timer/exynos4210_rtc.c @@ -31,7 +31,6 @@ #include "hw/ptimer.h" #include "hw/hw.h" -#include "qemu/timer.h" #include "sysemu/sysemu.h" #include "hw/arm/exynos4210.h" diff --git a/include/block/coroutine_int.h b/include/block/coroutine_int.h index 17eb71e723..f133d65af8 100644 --- a/include/block/coroutine_int.h +++ b/include/block/coroutine_int.h @@ -38,6 +38,9 @@ struct Coroutine { void *entry_arg; Coroutine *caller; QSLIST_ENTRY(Coroutine) pool_next; + + /* Coroutines that should be woken up when we yield or terminate */ + QTAILQ_HEAD(, Coroutine) co_queue_wakeup; QTAILQ_ENTRY(Coroutine) co_queue_next; }; @@ -45,5 +48,6 @@ Coroutine *qemu_coroutine_new(void); void qemu_coroutine_delete(Coroutine *co); CoroutineAction qemu_coroutine_switch(Coroutine *from, Coroutine *to, CoroutineAction action); +void coroutine_fn qemu_co_queue_run_restart(Coroutine *co); #endif diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 2e5f11f47f..af5258d414 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -49,9 +49,6 @@ typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value); typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr); void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); -/* This should only be used for ram local to a device. */ -void *qemu_get_ram_ptr(ram_addr_t addr); -void qemu_put_ram_ptr(void *addr); /* This should not be used by devices. */ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr); @@ -105,7 +102,6 @@ uint32_t lduw_phys(hwaddr addr); uint32_t ldl_phys(hwaddr addr); uint64_t ldq_phys(hwaddr addr); void stl_phys_notdirty(hwaddr addr, uint32_t val); -void stq_phys_notdirty(hwaddr addr, uint64_t val); void stw_phys(hwaddr addr, uint32_t val); void stl_phys(hwaddr addr, uint32_t val); void stq_phys(hwaddr addr, uint64_t val); diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 1b156fd58f..8d15f90417 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -46,6 +46,7 @@ void address_space_destroy_dispatch(AddressSpace *as); ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr); +void *qemu_get_ram_ptr(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr); diff --git a/include/exec/memory.h b/include/exec/memory.h index 9e88320113..fdf55feea1 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -26,6 +26,9 @@ #include "exec/ioport.h" #include "qemu/int128.h" +#define MAX_PHYS_ADDR_SPACE_BITS 62 +#define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1) + typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionPortio MemoryRegionPortio; typedef struct MemoryRegionMmio MemoryRegionMmio; @@ -126,7 +129,7 @@ struct MemoryRegion { ram_addr_t ram_addr; bool subpage; bool terminates; - bool readable; + bool romd_mode; bool ram; bool readonly; /* For RAM regions */ bool enabled; @@ -355,16 +358,16 @@ uint64_t memory_region_size(MemoryRegion *mr); bool memory_region_is_ram(MemoryRegion *mr); /** - * memory_region_is_romd: check whether a memory region is ROMD + * memory_region_is_romd: check whether a memory region is in ROMD mode * - * Returns %true is a memory region is ROMD and currently set to allow + * Returns %true if a memory region is a ROM device and currently set to allow * direct reads. * * @mr: the memory region being queried */ static inline bool memory_region_is_romd(MemoryRegion *mr) { - return mr->rom_device && mr->readable; + return mr->rom_device && mr->romd_mode; } /** @@ -502,18 +505,18 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr, void memory_region_set_readonly(MemoryRegion *mr, bool readonly); /** - * memory_region_rom_device_set_readable: enable/disable ROM readability + * memory_region_rom_device_set_romd: enable/disable ROMD mode * * Allows a ROM device (initialized with memory_region_init_rom_device() to - * to be marked as readable (default) or not readable. When it is readable, - * the device is mapped to guest memory. When not readable, reads are - * forwarded to the #MemoryRegion.read function. + * set to ROMD mode (default) or MMIO mode. When it is in ROMD mode, the + * device is mapped to guest memory and satisfies read access directly. + * When in MMIO mode, reads are forwarded to the #MemoryRegion.read function. + * Writes are always handled by the #MemoryRegion.write function. * * @mr: the memory region to be updated - * @readable: whether reads are satisified directly (%true) or via callbacks - * (%false) + * @romd_mode: %true to put the region into ROMD mode */ -void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable); +void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode); /** * memory_region_set_coalescing: Enable memory coalescing for the region. @@ -718,24 +721,34 @@ void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset); /** - * memory_region_find: locate a MemoryRegion in an address space + * memory_region_find: translate an address/size relative to a + * MemoryRegion into a #MemoryRegionSection. * - * Locates the first #MemoryRegion within an address space given by - * @address_space that overlaps the range given by @addr and @size. + * Locates the first #MemoryRegion within @mr that overlaps the range + * given by @addr and @size. * * Returns a #MemoryRegionSection that describes a contiguous overlap. * It will have the following characteristics: - * .@offset_within_address_space >= @addr - * .@offset_within_address_space + .@size <= @addr + @size * .@size = 0 iff no overlap was found * .@mr is non-%NULL iff an overlap was found * - * @address_space: a top-level (i.e. parentless) region that contains - * the region to be found - * @addr: start of the area within @address_space to be searched + * Remember that in the return value the @offset_within_region is + * relative to the returned region (in the .@mr field), not to the + * @mr argument. + * + * Similarly, the .@offset_within_address_space is relative to the + * address space that contains both regions, the passed and the + * returned one. However, in the special case where the @mr argument + * has no parent (and thus is the root of the address space), the + * following will hold: + * .@offset_within_address_space >= @addr + * .@offset_within_address_space + .@size <= @addr + @size + * + * @mr: a MemoryRegion within which @addr is a relative address + * @addr: start of the area within @as to be searched * @size: size of the area to be searched */ -MemoryRegionSection memory_region_find(MemoryRegion *address_space, +MemoryRegionSection memory_region_find(MemoryRegion *mr, hwaddr addr, uint64_t size); /** @@ -756,13 +769,12 @@ memory_region_section_addr(MemoryRegionSection *section, } /** - * memory_global_sync_dirty_bitmap: synchronize the dirty log for all memory + * address_space_sync_dirty_bitmap: synchronize the dirty log for all memory * * Synchronizes the dirty page log for an entire address space. - * @address_space: a top-level (i.e. parentless) region that contains the - * memory being synchronized + * @as: the address space that contains the memory being synchronized */ -void memory_global_sync_dirty_bitmap(MemoryRegion *address_space); +void address_space_sync_dirty_bitmap(AddressSpace *as); /** * memory_region_transaction_begin: Start a transaction. diff --git a/include/exec/poison.h b/include/exec/poison.h index 7d7b23b1fc..2341a75041 100644 --- a/include/exec/poison.h +++ b/include/exec/poison.h @@ -42,7 +42,6 @@ #pragma GCC poison ldl_phys #pragma GCC poison ldq_phys #pragma GCC poison stl_phys_notdirty -#pragma GCC poison stq_phys_notdirty #pragma GCC poison stw_phys #pragma GCC poison stl_phys #pragma GCC poison stq_phys diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 2bd7090248..663426cee8 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -7,7 +7,6 @@ #include "hw/isa/isa.h" #include "hw/block/fdc.h" #include "net/net.h" -#include "exec/memory.h" #include "hw/i386/ioapic.h" /* PC-style peripherals (also used by other machines). */ @@ -217,6 +216,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); .property = "vectors",\ /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\ .value = stringify(0xFFFFFFFF),\ + },{ \ + .driver = "virtio-net-pci", \ + .property = "ctrl_guest_offloads", \ + .value = "off", \ },{\ .driver = "e1000",\ .property = "romfile",\ diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index beeead7a1a..b315ac91a4 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -31,6 +31,8 @@ /* The feature bitmap for virtio net */ #define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ #define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Control channel offload + * configuration support */ #define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ #define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ #define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ @@ -190,6 +192,7 @@ typedef struct VirtIONet { size_t config_size; char *netclient_name; char *netclient_type; + uint64_t curr_guest_offloads; } VirtIONet; #define VIRTIO_NET_CTRL_MAC 1 @@ -229,6 +232,15 @@ struct virtio_net_ctrl_mq { #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 +/* + * Control network offloads + * + * Dynamic offloads are available with the + * VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit. + */ +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 + #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 + #define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ @@ -249,6 +261,7 @@ struct virtio_net_ctrl_mq { DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \ DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \ DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \ + DEFINE_PROP_BIT("ctrl_guest_offloads", _state, _field, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), \ DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false) #define DEFINE_VIRTIO_NET_PROPERTIES(_state, _field) \ diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h index 382f04c3c4..6cc4831df3 100644 --- a/include/qapi/qmp/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -15,7 +15,6 @@ #include "qapi/qmp/qobject.h" #include "qemu/queue.h" -#include "qemu/queue.h" typedef struct QListEntry { QObject *value; diff --git a/include/qemu-common.h b/include/qemu-common.h index b9057d18cf..cb82ef3d42 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -45,6 +45,7 @@ #if defined(__GLIBC__) # include <pty.h> #elif defined CONFIG_BSD +# include <termios.h> # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) # include <libutil.h> # else diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h index ccfccae2b4..ad4a9e5c3a 100644 --- a/include/qemu/config-file.h +++ b/include/qemu/config-file.h @@ -4,7 +4,6 @@ #include <stdio.h> #include "qemu/option.h" #include "qapi/error.h" -#include "qemu/option.h" QemuOptsList *qemu_find_opts(const char *group); QemuOptsList *qemu_find_opts_err(const char *group, Error **errp); diff --git a/linux-user/signal.c b/linux-user/signal.c index 1055507224..5da8452b2a 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -2528,7 +2528,8 @@ setup_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc) int err = 0; int i; - err |= __put_user(regs->active_tc.PC, &sc->sc_pc); + err |= __put_user(exception_resume_pc(regs), &sc->sc_pc); + regs->hflags &= ~MIPS_HFLAG_BMASK; __put_user(0, &sc->sc_regs[0]); for (i = 1; i < 32; ++i) { @@ -2620,6 +2621,15 @@ get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size) return (sp - frame_size) & ~7; } +static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env) +{ + if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) { + env->hflags &= ~MIPS_HFLAG_M16; + env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT; + env->active_tc.PC &= ~(target_ulong) 1; + } +} + # if defined(TARGET_ABI_MIPSO32) /* compare linux/arch/mips/kernel/signal.c:setup_frame() */ static void setup_frame(int sig, struct target_sigaction * ka, @@ -2662,6 +2672,7 @@ static void setup_frame(int sig, struct target_sigaction * ka, * since it returns to userland using eret * we cannot do this here, and we must set PC directly */ regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler; + mips_set_hflags_isa_mode_from_pc(regs); unlock_user_struct(frame, frame_addr, 1); return; @@ -2709,6 +2720,7 @@ long do_sigreturn(CPUMIPSState *regs) #endif regs->active_tc.PC = regs->CP0_EPC; + mips_set_hflags_isa_mode_from_pc(regs); /* I am not sure this is right, but it seems to work * maybe a problem with nested signals ? */ regs->CP0_EPC = 0; @@ -2771,6 +2783,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, * since it returns to userland using eret * we cannot do this here, and we must set PC directly */ env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler; + mips_set_hflags_isa_mode_from_pc(env); unlock_user_struct(frame, frame_addr, 1); return; @@ -2804,6 +2817,7 @@ long do_rt_sigreturn(CPUMIPSState *env) goto badframe; env->active_tc.PC = env->CP0_EPC; + mips_set_hflags_isa_mode_from_pc(env); /* I am not sure this is right, but it seems to work * maybe a problem with nested signals ? */ env->CP0_EPC = 0; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 30e93bc0d0..1b3c0ed5f7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5050,10 +5050,10 @@ static int open_self_maps(void *cpu_env, int fd) } if (h2g_valid(min) && h2g_valid(max)) { dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx - " %c%c%c%c %08" PRIx64 " %02x:%02x %d%s%s\n", + " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n", h2g(min), h2g(max), flag_r, flag_w, flag_x, flag_p, offset, dev_maj, dev_min, inode, - path[0] ? " " : "", path); + path[0] ? " " : "", path); } } @@ -213,7 +213,7 @@ struct FlatRange { hwaddr offset_in_region; AddrRange addr; uint8_t dirty_log_mask; - bool readable; + bool romd_mode; bool readonly; }; @@ -236,7 +236,7 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b) return a->mr == b->mr && addrrange_equal(a->addr, b->addr) && a->offset_in_region == b->offset_in_region - && a->readable == b->readable + && a->romd_mode == b->romd_mode && a->readonly == b->readonly; } @@ -276,7 +276,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2) r1->addr.size), int128_make64(r2->offset_in_region)) && r1->dirty_log_mask == r2->dirty_log_mask - && r1->readable == r2->readable + && r1->romd_mode == r2->romd_mode && r1->readonly == r2->readonly; } @@ -532,7 +532,7 @@ static void render_memory_region(FlatView *view, fr.offset_in_region = offset_in_region; fr.addr = addrrange_make(base, now); fr.dirty_log_mask = mr->dirty_log_mask; - fr.readable = mr->readable; + fr.romd_mode = mr->romd_mode; fr.readonly = readonly; flatview_insert(view, i, &fr); ++i; @@ -552,7 +552,7 @@ static void render_memory_region(FlatView *view, fr.offset_in_region = offset_in_region; fr.addr = addrrange_make(base, remain); fr.dirty_log_mask = mr->dirty_log_mask; - fr.readable = mr->readable; + fr.romd_mode = mr->romd_mode; fr.readonly = readonly; flatview_insert(view, i, &fr); } @@ -768,10 +768,6 @@ static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr) qemu_ram_free_from_ptr(mr->ram_addr); } -static void memory_region_destructor_iomem(MemoryRegion *mr) -{ -} - static void memory_region_destructor_rom_device(MemoryRegion *mr) { qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK); @@ -801,7 +797,7 @@ void memory_region_init(MemoryRegion *mr, mr->enabled = true; mr->terminates = false; mr->ram = false; - mr->readable = true; + mr->romd_mode = true; mr->readonly = false; mr->rom_device = false; mr->destructor = memory_region_destructor_none; @@ -929,7 +925,6 @@ void memory_region_init_io(MemoryRegion *mr, mr->ops = ops; mr->opaque = opaque; mr->terminates = true; - mr->destructor = memory_region_destructor_iomem; mr->ram_addr = ~(ram_addr_t)0; } @@ -1121,11 +1116,11 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly) } } -void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable) +void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode) { - if (mr->readable != readable) { + if (mr->romd_mode != romd_mode) { memory_region_transaction_begin(); - mr->readable = readable; + mr->romd_mode = romd_mode; memory_region_update_pending |= mr->enabled; memory_region_transaction_commit(); } @@ -1451,15 +1446,24 @@ static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr) sizeof(FlatRange), cmp_flatrange_addr); } -MemoryRegionSection memory_region_find(MemoryRegion *address_space, +MemoryRegionSection memory_region_find(MemoryRegion *mr, hwaddr addr, uint64_t size) { - AddressSpace *as = memory_region_to_address_space(address_space); - AddrRange range = addrrange_make(int128_make64(addr), - int128_make64(size)); - FlatRange *fr = address_space_lookup(as, range); MemoryRegionSection ret = { .mr = NULL, .size = 0 }; + MemoryRegion *root; + AddressSpace *as; + AddrRange range; + FlatRange *fr; + addr += mr->addr; + for (root = mr; root->parent; ) { + root = root->parent; + addr += root->addr; + } + + as = memory_region_to_address_space(root); + range = addrrange_make(int128_make64(addr), int128_make64(size)); + fr = address_space_lookup(as, range); if (!fr) { return ret; } @@ -1470,6 +1474,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space, } ret.mr = fr->mr; + ret.address_space = as; range = addrrange_intersection(range, fr->addr); ret.offset_within_region = fr->offset_in_region; ret.offset_within_region += int128_get64(int128_sub(range.start, @@ -1480,9 +1485,8 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space, return ret; } -void memory_global_sync_dirty_bitmap(MemoryRegion *address_space) +void address_space_sync_dirty_bitmap(AddressSpace *as) { - AddressSpace *as = memory_region_to_address_space(address_space); FlatRange *fr; FOR_EACH_FLAT_RANGE(fr, as->current_map) { @@ -1568,10 +1572,13 @@ void address_space_init(AddressSpace *as, MemoryRegion *root) as->root = root; as->current_map = g_new(FlatView, 1); flatview_init(as->current_map); + as->ioeventfd_nb = 0; + as->ioeventfds = NULL; QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); as->name = NULL; - memory_region_transaction_commit(); address_space_init_dispatch(as); + memory_region_update_pending |= root->enabled; + memory_region_transaction_commit(); } void address_space_destroy(AddressSpace *as) @@ -1584,6 +1591,7 @@ void address_space_destroy(AddressSpace *as) address_space_destroy_dispatch(as); flatview_destroy(as->current_map); g_free(as->current_map); + g_free(as->ioeventfds); } uint64_t io_mem_read(MemoryRegion *mr, hwaddr addr, unsigned size) @@ -1649,9 +1657,9 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, base + mr->addr + (hwaddr)int128_get64(mr->size) - 1, mr->priority, - mr->readable ? 'R' : '-', - !mr->readonly && !(mr->rom_device && mr->readable) ? 'W' - : '-', + mr->romd_mode ? 'R' : '-', + !mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W' + : '-', mr->name, mr->alias->name, mr->alias_offset, @@ -1664,9 +1672,9 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, base + mr->addr + (hwaddr)int128_get64(mr->size) - 1, mr->priority, - mr->readable ? 'R' : '-', - !mr->readonly && !(mr->rom_device && mr->readable) ? 'W' - : '-', + mr->romd_mode ? 'R' : '-', + !mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W' + : '-', mr->name); } @@ -63,7 +63,6 @@ #ifdef CONFIG_TRACE_SIMPLE #include "trace/simple.h" #endif -#include "ui/qemu-spice.h" #include "exec/memory.h" #include "qmp-commands.h" #include "hmp.h" diff --git a/net/tap-bsd.c b/net/tap-bsd.c index bcdb2682b5..f61d580963 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -44,7 +44,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, struct stat s; #endif -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ + defined(__OpenBSD__) || defined(__APPLE__) /* if no ifname is given, always start the search from tap0/tun0. */ int i; char dname[100]; diff --git a/page_cache.c b/page_cache.c index 938a79c9ea..a05db643cc 100644 --- a/page_cache.c +++ b/page_cache.c @@ -21,7 +21,6 @@ #include <sys/types.h> #include <stdbool.h> #include <glib.h> -#include <strings.h> #include "qemu-common.h" #include "migration/page_cache.h" diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin Binary files differindex ec9eeb12c6..c2a19b8930 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin diff --git a/qapi-schema-test.json b/qapi-schema-test.json index 9eae3501d7..4434fa3961 100644 --- a/qapi-schema-test.json +++ b/qapi-schema-test.json @@ -32,6 +32,21 @@ { 'union': 'UserDefUnion', 'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } } +# for testing native lists +{ 'union': 'UserDefNativeListUnion', + 'data': { 'integer': ['int'], + 's8': ['int8'], + 's16': ['int16'], + 's32': ['int32'], + 's64': ['int64'], + 'u8': ['uint8'], + 'u16': ['uint16'], + 'u32': ['uint32'], + 'u64': ['uint64'], + 'number': ['number'], + 'boolean': ['bool'], + 'string': ['str'] } } + # testing commands { 'command': 'user_def_cmd', 'data': {} } { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} } diff --git a/qapi-schema.json b/qapi-schema.json index 9302e7db01..ef1f657efb 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1609,12 +1609,12 @@ '*mode': 'NewImageMode' } } ## -# @BlockdevAction +# @TransactionAction # # A discriminated record of operations that can be performed with # @transaction. ## -{ 'union': 'BlockdevAction', +{ 'union': 'TransactionAction', 'data': { 'blockdev-snapshot-sync': 'BlockdevSnapshot' } } @@ -1622,25 +1622,24 @@ ## # @transaction # -# Atomically operate on a group of one or more block devices. If -# any operation fails, then the entire set of actions will be -# abandoned and the appropriate error returned. The only operation -# supported is currently blockdev-snapshot-sync. +# Executes a number of transactionable QMP commands atomically. If any +# operation fails, then the entire set of actions will be abandoned and the +# appropriate error returned. # # List of: -# @BlockdevAction: information needed for the device snapshot +# @TransactionAction: information needed for the respective operation # # Returns: nothing on success -# If @device is not a valid block device, DeviceNotFound +# Errors depend on the operations of the transaction # -# Note: The transaction aborts on the first failure. Therefore, there will -# be only one device or snapshot file returned in an error condition, and +# Note: The transaction aborts on the first failure. Therefore, there will be +# information on only one failed operation returned in an error condition, and # subsequent actions will not have been attempted. # # Since 1.1 ## { 'command': 'transaction', - 'data': { 'actions': [ 'BlockdevAction' ] } } + 'data': { 'actions': [ 'TransactionAction' ] } } ## # @blockdev-snapshot-sync @@ -3286,7 +3285,7 @@ '*rows' : 'int' } } ## -# @ChardevRingbuf: +# @ChardevMemory: # # Configuration info for memory chardevs # @@ -3294,7 +3293,7 @@ # # Since: 1.5 ## -{ 'type': 'ChardevRingbuf', 'data': { '*size' : 'int' } } +{ 'type': 'ChardevMemory', 'data': { '*size' : 'int' } } ## # @ChardevBackend: @@ -3321,7 +3320,7 @@ 'spicevmc' : 'ChardevSpiceChannel', 'spiceport' : 'ChardevSpicePort', 'vc' : 'ChardevVC', - 'memory' : 'ChardevRingbuf' } } + 'memory' : 'ChardevMemory' } } ## # @ChardevReturn: diff --git a/qemu-char.c b/qemu-char.c index cff2896065..d04b429a03 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2875,8 +2875,8 @@ static void ringbuf_chr_close(struct CharDriverState *chr) chr->opaque = NULL; } -static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts, - Error **errp) +static CharDriverState *qemu_chr_open_memory(ChardevMemory *opts, + Error **errp) { CharDriverState *chr; RingBufCharDriver *d; @@ -2888,7 +2888,7 @@ static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts, /* The size must be power of 2 */ if (d->size & (d->size - 1)) { - error_setg(errp, "size of ringbuf chardev must be power of two"); + error_setg(errp, "size of memory chardev must be power of two"); goto fail; } @@ -2920,7 +2920,7 @@ void qmp_ringbuf_write(const char *device, const char *data, CharDriverState *chr; const uint8_t *write_data; int ret; - size_t write_count; + gsize write_count; chr = qemu_chr_find(device); if (!chr) { @@ -3190,12 +3190,12 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend, backend->pipe->device = g_strdup(device); } -static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend, - Error **errp) +static void qemu_chr_parse_memory(QemuOpts *opts, ChardevBackend *backend, + Error **errp) { int val; - backend->memory = g_new0(ChardevRingbuf, 1); + backend->memory = g_new0(ChardevMemory, 1); val = qemu_opt_get_number(opts, "size", 0); if (val != 0) { @@ -3787,7 +3787,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, chr = vc_init(backend->vc); break; case CHARDEV_BACKEND_KIND_MEMORY: - chr = qemu_chr_open_ringbuf(backend->memory, errp); + chr = qemu_chr_open_memory(backend->memory, errp); break; default: error_setg(errp, "unknown chardev backend (%d)", backend->kind); @@ -3801,6 +3801,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, chr->label = g_strdup(id); chr->avail_connections = (backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1; + if (!chr->filename) { + chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]); + } QTAILQ_INSERT_TAIL(&chardevs, chr, next); return ret; } else { @@ -3832,7 +3835,7 @@ static void register_types(void) register_char_driver("socket", qemu_chr_open_socket); register_char_driver("udp", qemu_chr_open_udp); register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY, - qemu_chr_parse_ringbuf); + qemu_chr_parse_memory); register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE, qemu_chr_parse_file_out); register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO, diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c index 86efe1f86a..d9fea4989d 100644 --- a/qemu-coroutine-lock.c +++ b/qemu-coroutine-lock.c @@ -26,39 +26,11 @@ #include "block/coroutine.h" #include "block/coroutine_int.h" #include "qemu/queue.h" -#include "block/aio.h" #include "trace.h" -/* Coroutines are awoken from a BH to allow the current coroutine to complete - * its flow of execution. The BH may run after the CoQueue has been destroyed, - * so keep BH data in a separate heap-allocated struct. - */ -typedef struct { - QEMUBH *bh; - QTAILQ_HEAD(, Coroutine) entries; -} CoQueueNextData; - -static void qemu_co_queue_next_bh(void *opaque) -{ - CoQueueNextData *data = opaque; - Coroutine *next; - - trace_qemu_co_queue_next_bh(); - while ((next = QTAILQ_FIRST(&data->entries))) { - QTAILQ_REMOVE(&data->entries, next, co_queue_next); - qemu_coroutine_enter(next, NULL); - } - - qemu_bh_delete(data->bh); - g_slice_free(CoQueueNextData, data); -} - void qemu_co_queue_init(CoQueue *queue) { QTAILQ_INIT(&queue->entries); - - /* This will be exposed to callers once there are multiple AioContexts */ - queue->ctx = qemu_get_aio_context(); } void coroutine_fn qemu_co_queue_wait(CoQueue *queue) @@ -77,23 +49,37 @@ void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue) assert(qemu_in_coroutine()); } +/** + * qemu_co_queue_run_restart: + * + * Enter each coroutine that was previously marked for restart by + * qemu_co_queue_next() or qemu_co_queue_restart_all(). This function is + * invoked by the core coroutine code when the current coroutine yields or + * terminates. + */ +void qemu_co_queue_run_restart(Coroutine *co) +{ + Coroutine *next; + + trace_qemu_co_queue_run_restart(co); + while ((next = QTAILQ_FIRST(&co->co_queue_wakeup))) { + QTAILQ_REMOVE(&co->co_queue_wakeup, next, co_queue_next); + qemu_coroutine_enter(next, NULL); + } +} + static bool qemu_co_queue_do_restart(CoQueue *queue, bool single) { + Coroutine *self = qemu_coroutine_self(); Coroutine *next; - CoQueueNextData *data; if (QTAILQ_EMPTY(&queue->entries)) { return false; } - data = g_slice_new(CoQueueNextData); - data->bh = aio_bh_new(queue->ctx, qemu_co_queue_next_bh, data); - QTAILQ_INIT(&data->entries); - qemu_bh_schedule(data->bh); - while ((next = QTAILQ_FIRST(&queue->entries)) != NULL) { QTAILQ_REMOVE(&queue->entries, next, co_queue_next); - QTAILQ_INSERT_TAIL(&data->entries, next, co_queue_next); + QTAILQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next); trace_qemu_co_queue_next(next); if (single) { break; diff --git a/qemu-coroutine.c b/qemu-coroutine.c index 25a14c605d..423430d3a0 100644 --- a/qemu-coroutine.c +++ b/qemu-coroutine.c @@ -14,6 +14,7 @@ #include "trace.h" #include "qemu-common.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "block/coroutine_int.h" @@ -23,6 +24,7 @@ enum { }; /** Free list to speed up creation */ +static QemuMutex pool_lock; static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool); static unsigned int pool_size; @@ -30,31 +32,44 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry) { Coroutine *co; + qemu_mutex_lock(&pool_lock); co = QSLIST_FIRST(&pool); if (co) { QSLIST_REMOVE_HEAD(&pool, pool_next); pool_size--; - } else { + } + qemu_mutex_unlock(&pool_lock); + + if (!co) { co = qemu_coroutine_new(); } co->entry = entry; + QTAILQ_INIT(&co->co_queue_wakeup); return co; } static void coroutine_delete(Coroutine *co) { + qemu_mutex_lock(&pool_lock); if (pool_size < POOL_MAX_SIZE) { QSLIST_INSERT_HEAD(&pool, co, pool_next); co->caller = NULL; pool_size++; + qemu_mutex_unlock(&pool_lock); return; } + qemu_mutex_unlock(&pool_lock); qemu_coroutine_delete(co); } -static void __attribute__((destructor)) coroutine_cleanup(void) +static void __attribute__((constructor)) coroutine_pool_init(void) +{ + qemu_mutex_init(&pool_lock); +} + +static void __attribute__((destructor)) coroutine_pool_cleanup(void) { Coroutine *co; Coroutine *tmp; @@ -63,6 +78,8 @@ static void __attribute__((destructor)) coroutine_cleanup(void) QSLIST_REMOVE_HEAD(&pool, pool_next); qemu_coroutine_delete(co); } + + qemu_mutex_destroy(&pool_lock); } static void coroutine_swap(Coroutine *from, Coroutine *to) @@ -71,6 +88,8 @@ static void coroutine_swap(Coroutine *from, Coroutine *to) ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD); + qemu_co_queue_run_restart(to); + switch (ret) { case COROUTINE_YIELD: return; diff --git a/qemu-doc.texi b/qemu-doc.texi index 5fc0eae400..8022890391 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -1958,15 +1958,11 @@ SPARCbook The emulation is somewhat complete. SMP up to 16 CPUs is supported, but Linux limits the number of usable CPUs to 4. -It's also possible to simulate a SPARCstation 2 (sun4c architecture), -SPARCserver 1000, or SPARCcenter 2000 (sun4d architecture), but these -emulators are not usable yet. - -QEMU emulates the following sun4m/sun4c/sun4d peripherals: +QEMU emulates the following sun4m peripherals: @itemize @minus @item -IOMMU or IO-UNITs +IOMMU @item TCX Frame buffer @item @@ -2019,7 +2015,7 @@ qemu-system-sparc -prom-env 'auto-boot?=false' \ -prom-env 'boot-device=sd(0,2,0):d' -prom-env 'boot-args=linux single' @end example -@item -M [SS-4|SS-5|SS-10|SS-20|SS-600MP|LX|Voyager|SPARCClassic] [|SPARCbook|SS-2|SS-1000|SS-2000] +@item -M [SS-4|SS-5|SS-10|SS-20|SS-600MP|LX|Voyager|SPARCClassic] [|SPARCbook] Set the emulated machine type. Default is SS-5. @@ -1635,12 +1635,43 @@ static const cmdinfo_t alloc_cmd = { .oneline = "checks if a sector is present in the file", }; + +static int map_is_allocated(int64_t sector_num, int64_t nb_sectors, int64_t *pnum) +{ + int num, num_checked; + int ret, firstret; + + num_checked = MIN(nb_sectors, INT_MAX); + ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); + if (ret < 0) { + return ret; + } + + firstret = ret; + *pnum = num; + + while (nb_sectors > 0 && ret == firstret) { + sector_num += num; + nb_sectors -= num; + + num_checked = MIN(nb_sectors, INT_MAX); + ret = bdrv_is_allocated(bs, sector_num, num_checked, &num); + if (ret == firstret) { + *pnum += num; + } else { + break; + } + } + + return firstret; +} + static int map_f(int argc, char **argv) { int64_t offset; int64_t nb_sectors; char s1[64]; - int num, num_checked; + int64_t num; int ret; const char *retstr; @@ -1648,12 +1679,17 @@ static int map_f(int argc, char **argv) nb_sectors = bs->total_sectors; do { - num_checked = MIN(nb_sectors, INT_MAX); - ret = bdrv_is_allocated(bs, offset, num_checked, &num); + ret = map_is_allocated(offset, nb_sectors, &num); + if (ret < 0) { + error_report("Failed to get allocation status: %s", strerror(-ret)); + return 0; + } + retstr = ret ? " allocated" : "not allocated"; cvtstr(offset << 9ULL, s1, sizeof(s1)); - printf("[% 24" PRId64 "] % 8d/% 8d sectors %s at offset %s (%d)\n", - offset << 9ULL, num, num_checked, retstr, s1, ret); + printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s " + "at offset %s (%d)\n", + offset << 9ULL, num, nb_sectors, retstr, s1, ret); offset += num; nb_sectors -= num; diff --git a/qemu-options.hx b/qemu-options.hx index fb62b75ccb..bf94862b58 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1779,7 +1779,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, "-chardev msmouse,id=id[,mux=on|off]\n" "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n" " [,mux=on|off]\n" - "-chardev ringbuf,id=id[,size=size]\n" + "-chardev memory,id=id[,size=size]\n" "-chardev file,id=id,path=path[,mux=on|off]\n" "-chardev pipe,id=id,path=path[,mux=on|off]\n" #ifdef _WIN32 @@ -1817,7 +1817,7 @@ Backend is one of: @option{udp}, @option{msmouse}, @option{vc}, -@option{ringbuf}, +@option{memory}, @option{file}, @option{pipe}, @option{console}, @@ -1926,7 +1926,7 @@ the console, in pixels. @option{cols} and @option{rows} specify that the console be sized to fit a text console with the given dimensions. -@item -chardev ringbuf ,id=@var{id} [,size=@var{size}] +@item -chardev memory ,id=@var{id} [,size=@var{size}] Create a ring buffer with fixed size @option{size}. @var{size} must be a power of two, and defaults to @code{64K}). @@ -2528,6 +2528,7 @@ Redirect the monitor to host device @var{dev} (same devices as the serial port). The default device is @code{vc} in graphical mode and @code{stdio} in non graphical mode. +Use @code{-monitor none} to disable the default monitor. ETEXI DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \ "-qmp dev like -monitor but opens in 'control' mode\n", diff --git a/qobject/json-parser.c b/qobject/json-parser.c index 05279c11eb..e7947b340c 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -640,9 +640,29 @@ static QObject *parse_literal(JSONParserContext *ctxt) case JSON_STRING: obj = QOBJECT(qstring_from_escaped_str(ctxt, token)); break; - case JSON_INTEGER: - obj = QOBJECT(qint_from_int(strtoll(token_get_value(token), NULL, 10))); - break; + case JSON_INTEGER: { + /* A possibility exists that this is a whole-valued float where the + * fractional part was left out due to being 0 (.0). It's not a big + * deal to treat these as ints in the parser, so long as users of the + * resulting QObject know to expect a QInt in place of a QFloat in + * cases like these. + * + * However, in some cases these values will overflow/underflow a + * QInt/int64 container, thus we should assume these are to be handled + * as QFloats/doubles rather than silently changing their values. + * + * strtoll() indicates these instances by setting errno to ERANGE + */ + int64_t value; + + errno = 0; /* strtoll doesn't set errno on success */ + value = strtoll(token_get_value(token), NULL, 10); + if (errno != ERANGE) { + obj = QOBJECT(qint_from_int(value)); + break; + } + /* fall through to JSON_FLOAT */ + } case JSON_FLOAT: /* FIXME dependent on locale */ obj = QOBJECT(qfloat_from_double(strtod(token_get_value(token), NULL))); diff --git a/qom/object.c b/qom/object.c index ec88231fa9..803b94bb66 100644 --- a/qom/object.c +++ b/qom/object.c @@ -442,7 +442,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename, int i; Object *inst; - for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) { + for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) { if (obj->class->cast_cache[i] == typename) { goto out; } @@ -458,7 +458,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename, assert(obj == inst); - if (obj == inst) { + if (obj && obj == inst) { for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { obj->class->cast_cache[i - 1] = obj->class->cast_cache[i]; } diff --git a/roms/configure-seabios.sh b/roms/configure-seabios.sh index 4bb6c2b90f..98f59a24ba 100755 --- a/roms/configure-seabios.sh +++ b/roms/configure-seabios.sh @@ -2,4 +2,4 @@ config="$1" make -C seabios clean distclean cp "$config" seabios/.config -make -C seabios olddefconfig +make -C seabios oldnoconfig diff --git a/roms/seabios b/roms/seabios -Subproject 88cb66ea542906ffff8a80ef397b9e3adbb3311 +Subproject d4f7d90f47462b4e8836899adc5060fbde5253e diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 9e19920970..fd42d71da1 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -16,8 +16,21 @@ import os import getopt import errno -def generate_fwd_struct(name, members): +def generate_fwd_struct(name, members, builtin_type=False): + if builtin_type: + return mcgen(''' + +typedef struct %(name)sList +{ + %(type)s value; + struct %(name)sList *next; +} %(name)sList; +''', + type=c_type(name), + name=name) + return mcgen(''' + typedef struct %(name)s %(name)s; typedef struct %(name)sList @@ -164,6 +177,7 @@ void qapi_free_%(type)s(%(c_type)s obj); def generate_type_cleanup(name): ret = mcgen(''' + void qapi_free_%(type)s(%(c_type)s obj) { QapiDeallocVisitor *md; @@ -184,8 +198,9 @@ void qapi_free_%(type)s(%(c_type)s obj) try: - opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", - ["source", "header", "prefix=", "output-dir="]) + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:", + ["source", "header", "builtins", + "prefix=", "output-dir="]) except getopt.GetoptError, err: print str(err) sys.exit(1) @@ -197,6 +212,7 @@ h_file = 'qapi-types.h' do_c = False do_h = False +do_builtins = False for o, a in opts: if o in ("-p", "--prefix"): @@ -207,6 +223,8 @@ for o, a in opts: do_c = True elif o in ("-h", "--header"): do_h = True + elif o in ("-b", "--builtins"): + do_builtins = True if not do_c and not do_h: do_c = True @@ -282,6 +300,11 @@ fdecl.write(mcgen(''' exprs = parse_schema(sys.stdin) exprs = filter(lambda expr: not expr.has_key('gen'), exprs) +fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL")) +for typename in builtin_types: + fdecl.write(generate_fwd_struct(typename, None, builtin_type=True)) +fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL")) + for expr in exprs: ret = "\n" if expr.has_key('type'): @@ -298,6 +321,22 @@ for expr in exprs: continue fdecl.write(ret) +# to avoid header dependency hell, we always generate declarations +# for built-in types in our header files and simply guard them +fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL")) +for typename in builtin_types: + fdecl.write(generate_type_cleanup_decl(typename + "List")) +fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL")) + +# ...this doesn't work for cases where we link in multiple objects that +# have the functions defined, so we use -b option to provide control +# over these cases +if do_builtins: + fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) + for typename in builtin_types: + fdef.write(generate_type_cleanup(typename + "List")) + fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) + for expr in exprs: ret = "\n" if expr.has_key('type'): diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index a276540a18..6cac05acd5 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -174,7 +174,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** ''', abbrev = de_camel_case(name).upper(), enum = c_fun(de_camel_case(key),False).upper(), - c_type=members[key], + c_type=type_name(members[key]), c_name=c_fun(key)) ret += mcgen(''' @@ -202,12 +202,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** return ret -def generate_declaration(name, members, genlist=True): - ret = mcgen(''' +def generate_declaration(name, members, genlist=True, builtin_type=False): + ret = "" + if not builtin_type: + ret += mcgen(''' void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp); ''', - name=name) + name=name) if genlist: ret += mcgen(''' @@ -235,8 +237,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e name=name) try: - opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", - ["source", "header", "prefix=", "output-dir="]) + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:", + ["source", "header", "builtins", "prefix=", + "output-dir="]) except getopt.GetoptError, err: print str(err) sys.exit(1) @@ -248,6 +251,7 @@ h_file = 'qapi-visit.h' do_c = False do_h = False +do_builtins = False for o, a in opts: if o in ("-p", "--prefix"): @@ -258,6 +262,8 @@ for o, a in opts: do_c = True elif o in ("-h", "--header"): do_h = True + elif o in ("-b", "--builtins"): + do_builtins = True if not do_c and not do_h: do_c = True @@ -324,11 +330,29 @@ fdecl.write(mcgen(''' #include "qapi/visitor.h" #include "%(prefix)sqapi-types.h" + ''', prefix=prefix, guard=guardname(h_file))) exprs = parse_schema(sys.stdin) +# to avoid header dependency hell, we always generate declarations +# for built-in types in our header files and simply guard them +fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL")) +for typename in builtin_types: + fdecl.write(generate_declaration(typename, None, genlist=True, + builtin_type=True)) +fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) + +# ...this doesn't work for cases where we link in multiple objects that +# have the functions defined, so we use -b option to provide control +# over these cases +if do_builtins: + fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF")) + for typename in builtin_types: + fdef.write(generate_visit_list(typename, None)) + fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF")) + for expr in exprs: if expr.has_key('type'): ret = generate_visit_struct(expr['type'], expr['data']) diff --git a/scripts/qapi.py b/scripts/qapi.py index afc5f32aeb..02ad668ca3 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -11,6 +11,12 @@ from ordereddict import OrderedDict +builtin_types = [ + 'str', 'int', 'number', 'bool', + 'int8', 'int16', 'int32', 'int64', + 'uint8', 'uint16', 'uint32', 'uint64' +] + def tokenize(data): while len(data): ch = data[0] @@ -242,3 +248,20 @@ def guardname(filename): for substr in [".", " ", "-"]: guard = guard.replace(substr, "_") return guard.upper() + '_H' + +def guardstart(name): + return mcgen(''' + +#ifndef %(name)s +#define %(name)s + +''', + name=guardname(name)) + +def guardend(name): + return mcgen(''' + +#endif /* %(name)s */ + +''', + name=guardname(name)) diff --git a/slirp/misc.c b/slirp/misc.c index 8ecced547f..0bcc481939 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -242,8 +242,6 @@ strdup(str) } #endif -#include "monitor/monitor.h" - void lprint(const char *format, ...) { va_list args; diff --git a/target-arm/translate.c b/target-arm/translate.c index a1b7b8c1a8..71135bdef1 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -95,7 +95,7 @@ static TCGv_i32 cpu_exclusive_info; #endif /* FIXME: These should be removed. */ -static TCGv cpu_F0s, cpu_F1s; +static TCGv_i32 cpu_F0s, cpu_F1s; static TCGv_i64 cpu_F0d, cpu_F1d; #include "exec/gen-icount.h" @@ -138,16 +138,16 @@ void arm_translate_init(void) #include "helper.h" } -static inline TCGv load_cpu_offset(int offset) +static inline TCGv_i32 load_cpu_offset(int offset) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_ld_i32(tmp, cpu_env, offset); return tmp; } #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name)) -static inline void store_cpu_offset(TCGv var, int offset) +static inline void store_cpu_offset(TCGv_i32 var, int offset) { tcg_gen_st_i32(var, cpu_env, offset); tcg_temp_free_i32(var); @@ -157,7 +157,7 @@ static inline void store_cpu_offset(TCGv var, int offset) store_cpu_offset(var, offsetof(CPUARMState, name)) /* Set a variable to the value of a CPU register. */ -static void load_reg_var(DisasContext *s, TCGv var, int reg) +static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg) { if (reg == 15) { uint32_t addr; @@ -173,16 +173,16 @@ static void load_reg_var(DisasContext *s, TCGv var, int reg) } /* Create a new temporary and set it to the value of a CPU register. */ -static inline TCGv load_reg(DisasContext *s, int reg) +static inline TCGv_i32 load_reg(DisasContext *s, int reg) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); load_reg_var(s, tmp, reg); return tmp; } /* Set a CPU register. The source must be a temporary and will be marked as dead. */ -static void store_reg(DisasContext *s, int reg, TCGv var) +static void store_reg(DisasContext *s, int reg, TCGv_i32 var) { if (reg == 15) { tcg_gen_andi_i32(var, var, ~1); @@ -202,9 +202,9 @@ static void store_reg(DisasContext *s, int reg, TCGv var) #define gen_uxtb16(var) gen_helper_uxtb16(var, var) -static inline void gen_set_cpsr(TCGv var, uint32_t mask) +static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask) { - TCGv tmp_mask = tcg_const_i32(mask); + TCGv_i32 tmp_mask = tcg_const_i32(mask); gen_helper_cpsr_write(cpu_env, var, tmp_mask); tcg_temp_free_i32(tmp_mask); } @@ -213,16 +213,16 @@ static inline void gen_set_cpsr(TCGv var, uint32_t mask) static void gen_exception(int excp) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, excp); gen_helper_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); } -static void gen_smul_dual(TCGv a, TCGv b) +static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b) { - TCGv tmp1 = tcg_temp_new_i32(); - TCGv tmp2 = tcg_temp_new_i32(); + TCGv_i32 tmp1 = tcg_temp_new_i32(); + TCGv_i32 tmp2 = tcg_temp_new_i32(); tcg_gen_ext16s_i32(tmp1, a); tcg_gen_ext16s_i32(tmp2, b); tcg_gen_mul_i32(tmp1, tmp1, tmp2); @@ -235,9 +235,9 @@ static void gen_smul_dual(TCGv a, TCGv b) } /* Byteswap each halfword. */ -static void gen_rev16(TCGv var) +static void gen_rev16(TCGv_i32 var) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shri_i32(tmp, var, 8); tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff); tcg_gen_shli_i32(var, var, 8); @@ -247,7 +247,7 @@ static void gen_rev16(TCGv var) } /* Byteswap low halfword and sign extend. */ -static void gen_revsh(TCGv var) +static void gen_revsh(TCGv_i32 var) { tcg_gen_ext16u_i32(var, var); tcg_gen_bswap16_i32(var, var); @@ -255,7 +255,7 @@ static void gen_revsh(TCGv var) } /* Unsigned bitfield extract. */ -static void gen_ubfx(TCGv var, int shift, uint32_t mask) +static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask) { if (shift) tcg_gen_shri_i32(var, var, shift); @@ -263,7 +263,7 @@ static void gen_ubfx(TCGv var, int shift, uint32_t mask) } /* Signed bitfield extract. */ -static void gen_sbfx(TCGv var, int shift, int width) +static void gen_sbfx(TCGv_i32 var, int shift, int width) { uint32_t signbit; @@ -278,7 +278,7 @@ static void gen_sbfx(TCGv var, int shift, int width) } /* Return (b << 32) + a. Mark inputs as dead */ -static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b) +static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b) { TCGv_i64 tmp64 = tcg_temp_new_i64(); @@ -292,7 +292,7 @@ static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b) } /* Return (b << 32) - a. Mark inputs as dead. */ -static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b) +static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b) { TCGv_i64 tmp64 = tcg_temp_new_i64(); @@ -306,10 +306,10 @@ static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b) } /* 32x32->64 multiply. Marks inputs as dead. */ -static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) +static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b) { - TCGv lo = tcg_temp_new_i32(); - TCGv hi = tcg_temp_new_i32(); + TCGv_i32 lo = tcg_temp_new_i32(); + TCGv_i32 hi = tcg_temp_new_i32(); TCGv_i64 ret; tcg_gen_mulu2_i32(lo, hi, a, b); @@ -318,16 +318,16 @@ static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) ret = tcg_temp_new_i64(); tcg_gen_concat_i32_i64(ret, lo, hi); - tcg_temp_free(lo); - tcg_temp_free(hi); + tcg_temp_free_i32(lo); + tcg_temp_free_i32(hi); return ret; } -static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) +static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b) { - TCGv lo = tcg_temp_new_i32(); - TCGv hi = tcg_temp_new_i32(); + TCGv_i32 lo = tcg_temp_new_i32(); + TCGv_i32 hi = tcg_temp_new_i32(); TCGv_i64 ret; tcg_gen_muls2_i32(lo, hi, a, b); @@ -336,16 +336,16 @@ static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) ret = tcg_temp_new_i64(); tcg_gen_concat_i32_i64(ret, lo, hi); - tcg_temp_free(lo); - tcg_temp_free(hi); + tcg_temp_free_i32(lo); + tcg_temp_free_i32(hi); return ret; } /* Swap low and high halfwords. */ -static void gen_swap_half(TCGv var) +static void gen_swap_half(TCGv_i32 var) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shri_i32(tmp, var, 16); tcg_gen_shli_i32(var, var, 16); tcg_gen_or_i32(var, var, tmp); @@ -359,9 +359,9 @@ static void gen_swap_half(TCGv var) t0 = (t0 + t1) ^ tmp; */ -static void gen_add16(TCGv t0, TCGv t1) +static void gen_add16(TCGv_i32 t0, TCGv_i32 t1) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_xor_i32(tmp, t0, t1); tcg_gen_andi_i32(tmp, tmp, 0x8000); tcg_gen_andi_i32(t0, t0, ~0x8000); @@ -373,34 +373,34 @@ static void gen_add16(TCGv t0, TCGv t1) } /* Set CF to the top bit of var. */ -static void gen_set_CF_bit31(TCGv var) +static void gen_set_CF_bit31(TCGv_i32 var) { tcg_gen_shri_i32(cpu_CF, var, 31); } /* Set N and Z flags from var. */ -static inline void gen_logic_CC(TCGv var) +static inline void gen_logic_CC(TCGv_i32 var) { tcg_gen_mov_i32(cpu_NF, var); tcg_gen_mov_i32(cpu_ZF, var); } /* T0 += T1 + CF. */ -static void gen_adc(TCGv t0, TCGv t1) +static void gen_adc(TCGv_i32 t0, TCGv_i32 t1) { tcg_gen_add_i32(t0, t0, t1); tcg_gen_add_i32(t0, t0, cpu_CF); } /* dest = T0 + T1 + CF. */ -static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1) +static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { tcg_gen_add_i32(dest, t0, t1); tcg_gen_add_i32(dest, dest, cpu_CF); } /* dest = T0 - T1 + CF - 1. */ -static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) +static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { tcg_gen_sub_i32(dest, t0, t1); tcg_gen_add_i32(dest, dest, cpu_CF); @@ -408,9 +408,9 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) } /* dest = T0 + T1. Compute C, N, V and Z flags */ -static void gen_add_CC(TCGv dest, TCGv t0, TCGv t1) +static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, 0); tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp); tcg_gen_mov_i32(cpu_ZF, cpu_NF); @@ -422,9 +422,9 @@ static void gen_add_CC(TCGv dest, TCGv t0, TCGv t1) } /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */ -static void gen_adc_CC(TCGv dest, TCGv t0, TCGv t1) +static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); if (TCG_TARGET_HAS_add2_i32) { tcg_gen_movi_i32(tmp, 0); tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp); @@ -450,9 +450,9 @@ static void gen_adc_CC(TCGv dest, TCGv t0, TCGv t1) } /* dest = T0 - T1. Compute C, N, V and Z flags */ -static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1) +static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { - TCGv tmp; + TCGv_i32 tmp; tcg_gen_sub_i32(cpu_NF, t0, t1); tcg_gen_mov_i32(cpu_ZF, cpu_NF); tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1); @@ -465,18 +465,18 @@ static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1) } /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */ -static void gen_sbc_CC(TCGv dest, TCGv t0, TCGv t1) +static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_not_i32(tmp, t1); gen_adc_CC(dest, t0, tmp); - tcg_temp_free(tmp); + tcg_temp_free_i32(tmp); } #define GEN_SHIFT(name) \ -static void gen_##name(TCGv dest, TCGv t0, TCGv t1) \ +static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \ { \ - TCGv tmp1, tmp2, tmp3; \ + TCGv_i32 tmp1, tmp2, tmp3; \ tmp1 = tcg_temp_new_i32(); \ tcg_gen_andi_i32(tmp1, t1, 0xff); \ tmp2 = tcg_const_i32(0); \ @@ -492,9 +492,9 @@ GEN_SHIFT(shl) GEN_SHIFT(shr) #undef GEN_SHIFT -static void gen_sar(TCGv dest, TCGv t0, TCGv t1) +static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { - TCGv tmp1, tmp2; + TCGv_i32 tmp1, tmp2; tmp1 = tcg_temp_new_i32(); tcg_gen_andi_i32(tmp1, t1, 0xff); tmp2 = tcg_const_i32(0x1f); @@ -504,17 +504,17 @@ static void gen_sar(TCGv dest, TCGv t0, TCGv t1) tcg_temp_free_i32(tmp1); } -static void tcg_gen_abs_i32(TCGv dest, TCGv src) +static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src) { - TCGv c0 = tcg_const_i32(0); - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 c0 = tcg_const_i32(0); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_neg_i32(tmp, src); tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp); tcg_temp_free_i32(c0); tcg_temp_free_i32(tmp); } -static void shifter_out_im(TCGv var, int shift) +static void shifter_out_im(TCGv_i32 var, int shift) { if (shift == 0) { tcg_gen_andi_i32(cpu_CF, var, 1); @@ -527,7 +527,8 @@ static void shifter_out_im(TCGv var, int shift) } /* Shift by immediate. Includes special handling for shift == 0. */ -static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) +static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop, + int shift, int flags) { switch (shiftop) { case 0: /* LSL */ @@ -564,7 +565,7 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) shifter_out_im(var, shift - 1); tcg_gen_rotri_i32(var, var, shift); break; } else { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_shli_i32(tmp, cpu_CF, 31); if (flags) shifter_out_im(var, 0); @@ -575,8 +576,8 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) } }; -static inline void gen_arm_shift_reg(TCGv var, int shiftop, - TCGv shift, int flags) +static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop, + TCGv_i32 shift, int flags) { if (flags) { switch (shiftop) { @@ -612,7 +613,7 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop, case 4: gen_pas_helper(glue(pfx,add8)); break; \ case 7: gen_pas_helper(glue(pfx,sub8)); break; \ } -static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) +static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b) { TCGv_ptr tmp; @@ -659,7 +660,7 @@ static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) case 5: gen_pas_helper(glue(pfx,sub16)); break; \ case 6: gen_pas_helper(glue(pfx,subaddx)); break; \ } -static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) +static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b) { TCGv_ptr tmp; @@ -698,7 +699,7 @@ static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) static void gen_test_cc(int cc, int label) { - TCGv tmp; + TCGv_i32 tmp; int inv; switch (cc) { @@ -792,7 +793,7 @@ static const uint8_t table_logic_cc[16] = { /* Set PC and Thumb state from an immediate address. */ static inline void gen_bx_im(DisasContext *s, uint32_t addr) { - TCGv tmp; + TCGv_i32 tmp; s->is_jmp = DISAS_UPDATE; if (s->thumb != (addr & 1)) { @@ -805,7 +806,7 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr) } /* Set PC and Thumb state from var. var is marked as dead. */ -static inline void gen_bx(DisasContext *s, TCGv var) +static inline void gen_bx(DisasContext *s, TCGv_i32 var) { s->is_jmp = DISAS_UPDATE; tcg_gen_andi_i32(cpu_R[15], var, ~1); @@ -817,7 +818,7 @@ static inline void gen_bx(DisasContext *s, TCGv var) to r15 in ARM architecture v7 and above. The source must be a temporary and will be marked as dead. */ static inline void store_reg_bx(CPUARMState *env, DisasContext *s, - int reg, TCGv var) + int reg, TCGv_i32 var) { if (reg == 15 && ENABLE_ARCH_7) { gen_bx(s, var); @@ -831,7 +832,7 @@ static inline void store_reg_bx(CPUARMState *env, DisasContext *s, * the results of a LDR/LDM/POP into r15, and corresponds to the cases * in the ARM ARM which use the LoadWritePC() pseudocode function. */ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s, - int reg, TCGv var) + int reg, TCGv_i32 var) { if (reg == 15 && ENABLE_ARCH_5) { gen_bx(s, var); @@ -840,63 +841,6 @@ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s, } } -static inline TCGv gen_ld8s(TCGv addr, int index) -{ - TCGv tmp = tcg_temp_new_i32(); - tcg_gen_qemu_ld8s(tmp, addr, index); - return tmp; -} -static inline TCGv gen_ld8u(TCGv addr, int index) -{ - TCGv tmp = tcg_temp_new_i32(); - tcg_gen_qemu_ld8u(tmp, addr, index); - return tmp; -} -static inline TCGv gen_ld16s(TCGv addr, int index) -{ - TCGv tmp = tcg_temp_new_i32(); - tcg_gen_qemu_ld16s(tmp, addr, index); - return tmp; -} -static inline TCGv gen_ld16u(TCGv addr, int index) -{ - TCGv tmp = tcg_temp_new_i32(); - tcg_gen_qemu_ld16u(tmp, addr, index); - return tmp; -} -static inline TCGv gen_ld32(TCGv addr, int index) -{ - TCGv tmp = tcg_temp_new_i32(); - tcg_gen_qemu_ld32u(tmp, addr, index); - return tmp; -} -static inline TCGv_i64 gen_ld64(TCGv addr, int index) -{ - TCGv_i64 tmp = tcg_temp_new_i64(); - tcg_gen_qemu_ld64(tmp, addr, index); - return tmp; -} -static inline void gen_st8(TCGv val, TCGv addr, int index) -{ - tcg_gen_qemu_st8(val, addr, index); - tcg_temp_free_i32(val); -} -static inline void gen_st16(TCGv val, TCGv addr, int index) -{ - tcg_gen_qemu_st16(val, addr, index); - tcg_temp_free_i32(val); -} -static inline void gen_st32(TCGv val, TCGv addr, int index) -{ - tcg_gen_qemu_st32(val, addr, index); - tcg_temp_free_i32(val); -} -static inline void gen_st64(TCGv_i64 val, TCGv addr, int index) -{ - tcg_gen_qemu_st64(val, addr, index); - tcg_temp_free_i64(val); -} - static inline void gen_set_pc_im(uint32_t val) { tcg_gen_movi_i32(cpu_R[15], val); @@ -910,10 +854,10 @@ static inline void gen_lookup_tb(DisasContext *s) } static inline void gen_add_data_offset(DisasContext *s, unsigned int insn, - TCGv var) + TCGv_i32 var) { int val, rm, shift, shiftop; - TCGv offset; + TCGv_i32 offset; if (!(insn & (1 << 25))) { /* immediate */ @@ -938,10 +882,10 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn, } static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, - int extra, TCGv var) + int extra, TCGv_i32 var) { int val, rm; - TCGv offset; + TCGv_i32 offset; if (insn & (1 << 22)) { /* immediate */ @@ -1104,7 +1048,7 @@ VFP_GEN_FTOI(tosiz) #define VFP_GEN_FIX(name) \ static inline void gen_vfp_##name(int dp, int shift, int neon) \ { \ - TCGv tmp_shift = tcg_const_i32(shift); \ + TCGv_i32 tmp_shift = tcg_const_i32(shift); \ TCGv_ptr statusptr = get_fpstatus_ptr(neon); \ if (dp) { \ gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \ @@ -1124,7 +1068,7 @@ VFP_GEN_FIX(uhto) VFP_GEN_FIX(ulto) #undef VFP_GEN_FIX -static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr) +static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr) { if (dp) tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s)); @@ -1132,7 +1076,7 @@ static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr) tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s)); } -static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr) +static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr) { if (dp) tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s)); @@ -1164,14 +1108,14 @@ neon_reg_offset (int reg, int n) return vfp_reg_offset(0, sreg); } -static TCGv neon_load_reg(int reg, int pass) +static TCGv_i32 neon_load_reg(int reg, int pass) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass)); return tmp; } -static void neon_store_reg(int reg, int pass, TCGv var) +static void neon_store_reg(int reg, int pass, TCGv_i32 var) { tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass)); tcg_temp_free_i32(var); @@ -1228,14 +1172,14 @@ static inline void iwmmxt_store_reg(TCGv_i64 var, int reg) tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg])); } -static inline TCGv iwmmxt_load_creg(int reg) +static inline TCGv_i32 iwmmxt_load_creg(int reg) { - TCGv var = tcg_temp_new_i32(); + TCGv_i32 var = tcg_temp_new_i32(); tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg])); return var; } -static inline void iwmmxt_store_creg(int reg, TCGv var) +static inline void iwmmxt_store_creg(int reg, TCGv_i32 var) { tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg])); tcg_temp_free_i32(var); @@ -1353,7 +1297,7 @@ IWMMXT_OP_ENV(packsq) static void gen_op_iwmmxt_set_mup(void) { - TCGv tmp; + TCGv_i32 tmp; tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); tcg_gen_ori_i32(tmp, tmp, 2); store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); @@ -1361,7 +1305,7 @@ static void gen_op_iwmmxt_set_mup(void) static void gen_op_iwmmxt_set_cup(void) { - TCGv tmp; + TCGv_i32 tmp; tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); tcg_gen_ori_i32(tmp, tmp, 1); store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); @@ -1369,7 +1313,7 @@ static void gen_op_iwmmxt_set_cup(void) static void gen_op_iwmmxt_setpsr_nz(void) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0); store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]); } @@ -1381,11 +1325,12 @@ static inline void gen_op_iwmmxt_addl_M0_wRn(int rn) tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); } -static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest) +static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, + TCGv_i32 dest) { int rd; uint32_t offset; - TCGv tmp; + TCGv_i32 tmp; rd = (insn >> 16) & 0xf; tmp = load_reg(s, rd); @@ -1415,10 +1360,10 @@ static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest) return 0; } -static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest) +static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest) { int rd = (insn >> 0) & 0xf; - TCGv tmp; + TCGv_i32 tmp; if (insn & (1 << 8)) { if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) { @@ -1443,8 +1388,8 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) { int rd, wrd; int rdhi, rdlo, rd0, rd1, i; - TCGv addr; - TCGv tmp, tmp2, tmp3; + TCGv_i32 addr; + TCGv_i32 tmp, tmp2, tmp3; if ((insn & 0x0e000e00) == 0x0c000000) { if ((insn & 0x0fe00ff0) == 0x0c400000) { @@ -1482,13 +1427,15 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s)); i = 0; } else { /* WLDRW wRd */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); } } else { + tmp = tcg_temp_new_i32(); if (insn & (1 << 22)) { /* WLDRH */ - tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); } else { /* WLDRB */ - tmp = gen_ld8u(addr, IS_USER(s)); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); } } if (i) { @@ -1500,28 +1447,28 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) } else { if ((insn >> 28) == 0xf) { /* WSTRW wCx */ tmp = iwmmxt_load_creg(wrd); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); } else { gen_op_iwmmxt_movq_M0_wRn(wrd); tmp = tcg_temp_new_i32(); if (insn & (1 << 8)) { if (insn & (1 << 22)) { /* WSTRD */ - tcg_temp_free_i32(tmp); tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s)); } else { /* WSTRW wRd */ tcg_gen_trunc_i64_i32(tmp, cpu_M0); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); } } else { if (insn & (1 << 22)) { /* WSTRH */ tcg_gen_trunc_i64_i32(tmp, cpu_M0); - gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); } else { /* WSTRB */ tcg_gen_trunc_i64_i32(tmp, cpu_M0); - gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); } } } + tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); return 0; @@ -1796,12 +1743,12 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) tmp3 = tcg_const_i32((insn & 1) << 5); break; default: - TCGV_UNUSED(tmp2); - TCGV_UNUSED(tmp3); + TCGV_UNUSED_I32(tmp2); + TCGV_UNUSED_I32(tmp3); } gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3); - tcg_temp_free(tmp3); - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp3); + tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); @@ -2260,7 +2207,7 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) tmp = tcg_const_i32((insn >> 20) & 3); iwmmxt_load_reg(cpu_V1, rd1); gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); - tcg_temp_free(tmp); + tcg_temp_free_i32(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); break; @@ -2316,7 +2263,7 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) gen_op_iwmmxt_movq_M0_wRn(rd0); tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f)); gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp); - tcg_temp_free(tmp); + tcg_temp_free_i32(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); gen_op_iwmmxt_set_cup(); @@ -2446,7 +2393,7 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn) { int acc, rd0, rd1, rdhi, rdlo; - TCGv tmp, tmp2; + TCGv_i32 tmp, tmp2; if ((insn & 0x0ff00f10) == 0x0e200010) { /* Multiply with Internal Accumulate Format */ @@ -2532,22 +2479,22 @@ static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn) #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) /* Move between integer and VFP cores. */ -static TCGv gen_vfp_mrs(void) +static TCGv_i32 gen_vfp_mrs(void) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_mov_i32(tmp, cpu_F0s); return tmp; } -static void gen_vfp_msr(TCGv tmp) +static void gen_vfp_msr(TCGv_i32 tmp) { tcg_gen_mov_i32(cpu_F0s, tmp); tcg_temp_free_i32(tmp); } -static void gen_neon_dup_u8(TCGv var, int shift) +static void gen_neon_dup_u8(TCGv_i32 var, int shift) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); if (shift) tcg_gen_shri_i32(var, var, shift); tcg_gen_ext8u_i32(var, var); @@ -2558,39 +2505,39 @@ static void gen_neon_dup_u8(TCGv var, int shift) tcg_temp_free_i32(tmp); } -static void gen_neon_dup_low16(TCGv var) +static void gen_neon_dup_low16(TCGv_i32 var) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_ext16u_i32(var, var); tcg_gen_shli_i32(tmp, var, 16); tcg_gen_or_i32(var, var, tmp); tcg_temp_free_i32(tmp); } -static void gen_neon_dup_high16(TCGv var) +static void gen_neon_dup_high16(TCGv_i32 var) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_andi_i32(var, var, 0xffff0000); tcg_gen_shri_i32(tmp, var, 16); tcg_gen_or_i32(var, var, tmp); tcg_temp_free_i32(tmp); } -static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size) +static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size) { /* Load a single Neon element and replicate into a 32 bit TCG reg */ - TCGv tmp; + TCGv_i32 tmp = tcg_temp_new_i32(); switch (size) { case 0: - tmp = gen_ld8u(addr, IS_USER(s)); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); gen_neon_dup_u8(tmp, 0); break; case 1: - tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); gen_neon_dup_low16(tmp); break; case 2: - tmp = gen_ld32(addr, IS_USER(s)); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); break; default: /* Avoid compiler warnings. */ abort(); @@ -2604,9 +2551,9 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn) { uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; int dp, veclen; - TCGv addr; - TCGv tmp; - TCGv tmp2; + TCGv_i32 addr; + TCGv_i32 tmp; + TCGv_i32 tmp2; if (!arm_feature(env, ARM_FEATURE_VFP)) return 1; @@ -3428,7 +3375,7 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest) } } -static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y) +static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y) { if (x) tcg_gen_sari_i32(t0, t0, 16); @@ -3475,9 +3422,9 @@ static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) } /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */ -static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0) +static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0) { - TCGv tmp; + TCGv_i32 tmp; if (spsr) { /* ??? This is also undefined in system mode. */ if (IS_USER(s)) @@ -3499,16 +3446,16 @@ static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0) /* Returns nonzero if access to the PSR is not permitted. */ static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val) { - TCGv tmp; + TCGv_i32 tmp; tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, val); return gen_set_psr(s, mask, spsr, tmp); } /* Generate an old-style exception return. Marks pc as dead. */ -static void gen_exception_return(DisasContext *s, TCGv pc) +static void gen_exception_return(DisasContext *s, TCGv_i32 pc) { - TCGv tmp; + TCGv_i32 tmp; store_reg(s, 15, pc); tmp = load_cpu_field(spsr); gen_set_cpsr(tmp, 0xffffffff); @@ -3517,7 +3464,7 @@ static void gen_exception_return(DisasContext *s, TCGv pc) } /* Generate a v6 exception return. Marks both values as dead. */ -static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr) +static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr) { gen_set_cpsr(cpsr, 0xffffffff); tcg_temp_free_i32(cpsr); @@ -3530,7 +3477,7 @@ gen_set_condexec (DisasContext *s) { if (s->condexec_mask) { uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, val); store_cpu_field(tmp, condexec_bits); } @@ -3561,7 +3508,7 @@ static void gen_nop_hint(DisasContext *s, int val) #define CPU_V001 cpu_V0, cpu_V0, cpu_V1 -static inline void gen_neon_add(int size, TCGv t0, TCGv t1) +static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1) { switch (size) { case 0: gen_helper_neon_add_u8(t0, t0, t1); break; @@ -3571,7 +3518,7 @@ static inline void gen_neon_add(int size, TCGv t0, TCGv t1) } } -static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1) +static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1) { switch (size) { case 0: gen_helper_neon_sub_u8(t0, t1, t0); break; @@ -3633,22 +3580,22 @@ static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1) default: return 1; \ }} while (0) -static TCGv neon_load_scratch(int scratch) +static TCGv_i32 neon_load_scratch(int scratch) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); return tmp; } -static void neon_store_scratch(int scratch, TCGv var) +static void neon_store_scratch(int scratch, TCGv_i32 var) { tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); tcg_temp_free_i32(var); } -static inline TCGv neon_get_scalar(int size, int reg) +static inline TCGv_i32 neon_get_scalar(int size, int reg) { - TCGv tmp; + TCGv_i32 tmp; if (size == 1) { tmp = neon_load_reg(reg & 7, reg >> 4); if (reg & 8) { @@ -3664,7 +3611,7 @@ static inline TCGv neon_get_scalar(int size, int reg) static int gen_neon_unzip(int rd, int rm, int size, int q) { - TCGv tmp, tmp2; + TCGv_i32 tmp, tmp2; if (!q && size == 2) { return 1; } @@ -3703,7 +3650,7 @@ static int gen_neon_unzip(int rd, int rm, int size, int q) static int gen_neon_zip(int rd, int rm, int size, int q) { - TCGv tmp, tmp2; + TCGv_i32 tmp, tmp2; if (!q && size == 2) { return 1; } @@ -3740,9 +3687,9 @@ static int gen_neon_zip(int rd, int rm, int size, int q) return 0; } -static void gen_neon_trn_u8(TCGv t0, TCGv t1) +static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1) { - TCGv rd, tmp; + TCGv_i32 rd, tmp; rd = tcg_temp_new_i32(); tmp = tcg_temp_new_i32(); @@ -3762,9 +3709,9 @@ static void gen_neon_trn_u8(TCGv t0, TCGv t1) tcg_temp_free_i32(rd); } -static void gen_neon_trn_u16(TCGv t0, TCGv t1) +static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1) { - TCGv rd, tmp; + TCGv_i32 rd, tmp; rd = tcg_temp_new_i32(); tmp = tcg_temp_new_i32(); @@ -3816,9 +3763,9 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) int load; int shift; int n; - TCGv addr; - TCGv tmp; - TCGv tmp2; + TCGv_i32 addr; + TCGv_i32 tmp; + TCGv_i32 tmp2; TCGv_i64 tmp64; if (!s->vfp_enabled) @@ -3865,32 +3812,36 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tcg_gen_addi_i32(addr, addr, 1 << size); } if (size == 3) { + tmp64 = tcg_temp_new_i64(); if (load) { - tmp64 = gen_ld64(addr, IS_USER(s)); + tcg_gen_qemu_ld64(tmp64, addr, IS_USER(s)); neon_store_reg64(tmp64, rd); - tcg_temp_free_i64(tmp64); } else { - tmp64 = tcg_temp_new_i64(); neon_load_reg64(tmp64, rd); - gen_st64(tmp64, addr, IS_USER(s)); + tcg_gen_qemu_st64(tmp64, addr, IS_USER(s)); } + tcg_temp_free_i64(tmp64); tcg_gen_addi_i32(addr, addr, stride); } else { for (pass = 0; pass < 2; pass++) { if (size == 2) { if (load) { - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); neon_store_reg(rd, pass, tmp); } else { tmp = neon_load_reg(rd, pass); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_gen_addi_i32(addr, addr, stride); } else if (size == 1) { if (load) { - tmp = gen_ld16u(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); tcg_gen_addi_i32(addr, addr, stride); - tmp2 = gen_ld16u(addr, IS_USER(s)); + tmp2 = tcg_temp_new_i32(); + tcg_gen_qemu_ld16u(tmp2, addr, IS_USER(s)); tcg_gen_addi_i32(addr, addr, stride); tcg_gen_shli_i32(tmp2, tmp2, 16); tcg_gen_or_i32(tmp, tmp, tmp2); @@ -3900,16 +3851,19 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tmp = neon_load_reg(rd, pass); tmp2 = tcg_temp_new_i32(); tcg_gen_shri_i32(tmp2, tmp, 16); - gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); tcg_gen_addi_i32(addr, addr, stride); - gen_st16(tmp2, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp2, addr, IS_USER(s)); + tcg_temp_free_i32(tmp2); tcg_gen_addi_i32(addr, addr, stride); } } else /* size == 0 */ { if (load) { - TCGV_UNUSED(tmp2); + TCGV_UNUSED_I32(tmp2); for (n = 0; n < 4; n++) { - tmp = gen_ld8u(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); tcg_gen_addi_i32(addr, addr, stride); if (n == 0) { tmp2 = tmp; @@ -3929,7 +3883,8 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) } else { tcg_gen_shri_i32(tmp, tmp2, n * 8); } - gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); tcg_gen_addi_i32(addr, addr, stride); } tcg_temp_free_i32(tmp2); @@ -4049,15 +4004,16 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) load_reg_var(s, addr, rn); for (reg = 0; reg < nregs; reg++) { if (load) { + tmp = tcg_temp_new_i32(); switch (size) { case 0: - tmp = gen_ld8u(addr, IS_USER(s)); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); break; case 1: - tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); break; case 2: - tmp = gen_ld32(addr, IS_USER(s)); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); break; default: /* Avoid compiler warnings. */ abort(); @@ -4075,15 +4031,16 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tcg_gen_shri_i32(tmp, tmp, shift); switch (size) { case 0: - gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); break; case 1: - gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); break; case 2: - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); break; } + tcg_temp_free_i32(tmp); } rd += stride; tcg_gen_addi_i32(addr, addr, 1 << size); @@ -4093,13 +4050,13 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) } } if (rm != 15) { - TCGv base; + TCGv_i32 base; base = load_reg(s, rn); if (rm == 13) { tcg_gen_addi_i32(base, base, stride); } else { - TCGv index; + TCGv_i32 index; index = load_reg(s, rm); tcg_gen_add_i32(base, base, index); tcg_temp_free_i32(index); @@ -4110,14 +4067,14 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) } /* Bitwise select. dest = c ? t : f. Clobbers T and F. */ -static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c) +static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c) { tcg_gen_and_i32(t, t, c); tcg_gen_andc_i32(f, f, c); tcg_gen_or_i32(dest, t, f); } -static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src) +static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src) { switch (size) { case 0: gen_helper_neon_narrow_u8(dest, src); break; @@ -4127,7 +4084,7 @@ static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src) } } -static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src) +static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src) { switch (size) { case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break; @@ -4137,7 +4094,7 @@ static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src) } } -static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src) +static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src) { switch (size) { case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break; @@ -4147,7 +4104,7 @@ static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src) } } -static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src) +static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src) { switch (size) { case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break; @@ -4157,7 +4114,7 @@ static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src) } } -static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift, +static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift, int q, int u) { if (q) { @@ -4191,7 +4148,7 @@ static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift, } } -static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u) +static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u) { if (u) { switch (size) { @@ -4252,7 +4209,8 @@ static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size) } } -static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u) +static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b, + int size, int u) { TCGv_i64 tmp; @@ -4282,7 +4240,8 @@ static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u) } } -static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src) +static void gen_neon_narrow_op(int op, int u, int size, + TCGv_i32 dest, TCGv_i64 src) { if (op) { if (u) { @@ -4493,7 +4452,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins int pairwise; int u; uint32_t imm, mask; - TCGv tmp, tmp2, tmp3, tmp4, tmp5; + TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5; TCGv_i64 tmp64; if (!s->vfp_enabled) @@ -5450,11 +5409,11 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins tmp = neon_load_reg(rn, 1); neon_store_scratch(2, tmp); } - TCGV_UNUSED(tmp3); + TCGV_UNUSED_I32(tmp3); for (pass = 0; pass < 2; pass++) { if (src1_wide) { neon_load_reg64(cpu_V0, rn + pass); - TCGV_UNUSED(tmp); + TCGV_UNUSED_I32(tmp); } else { if (pass == 1 && rd == rn) { tmp = neon_load_scratch(2); @@ -5467,7 +5426,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins } if (src2_wide) { neon_load_reg64(cpu_V1, rm + pass); - TCGV_UNUSED(tmp2); + TCGV_UNUSED_I32(tmp2); } else { if (pass == 1 && rd == rm) { tmp2 = neon_load_scratch(2); @@ -5881,7 +5840,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins if (rm & 1) { return 1; } - TCGV_UNUSED(tmp2); + TCGV_UNUSED_I32(tmp2); for (pass = 0; pass < 2; pass++) { neon_load_reg64(cpu_V0, rm + pass); tmp = tcg_temp_new_i32(); @@ -5963,7 +5922,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins if (neon_2rm_is_float_op(op)) { tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass)); - TCGV_UNUSED(tmp); + TCGV_UNUSED_I32(tmp); } else { tmp = neon_load_reg(rm, pass); } @@ -6036,7 +5995,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break; default: abort(); } - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); if (op == NEON_2RM_VCLE0) { tcg_gen_not_i32(tmp, tmp); } @@ -6049,7 +6008,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break; default: abort(); } - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); if (op == NEON_2RM_VCLT0) { tcg_gen_not_i32(tmp, tmp); } @@ -6062,7 +6021,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; default: abort(); } - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); break; case NEON_2RM_VABS: switch(size) { @@ -6075,14 +6034,14 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins case NEON_2RM_VNEG: tmp2 = tcg_const_i32(0); gen_neon_rsb(size, tmp, tmp2); - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); break; case NEON_2RM_VCGT0_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus); - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } @@ -6091,7 +6050,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus); - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } @@ -6100,7 +6059,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus); - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } @@ -6109,7 +6068,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus); - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } @@ -6118,7 +6077,7 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins TCGv_ptr fpstatus = get_fpstatus_ptr(1); tmp2 = tcg_const_i32(0); gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus); - tcg_temp_free(tmp2); + tcg_temp_free_i32(tmp2); tcg_temp_free_ptr(fpstatus); break; } @@ -6346,7 +6305,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tcg_temp_free_i64(tmp64); store_reg(s, rt2, tmp); } else { - TCGv tmp; + TCGv_i32 tmp; if (ri->type & ARM_CP_CONST) { tmp = tcg_const_i32(ri->resetvalue); } else if (ri->readfn) { @@ -6377,7 +6336,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) } if (is64) { - TCGv tmplo, tmphi; + TCGv_i32 tmplo, tmphi; TCGv_i64 tmp64 = tcg_temp_new_i64(); tmplo = load_reg(s, rt); tmphi = load_reg(s, rt2); @@ -6395,7 +6354,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tcg_temp_free_i64(tmp64); } else { if (ri->writefn) { - TCGv tmp; + TCGv_i32 tmp; TCGv_ptr tmpptr; gen_set_pc_im(s->pc); tmp = load_reg(s, rt); @@ -6404,7 +6363,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) tcg_temp_free_ptr(tmpptr); tcg_temp_free_i32(tmp); } else { - TCGv tmp = load_reg(s, rt); + TCGv_i32 tmp = load_reg(s, rt); store_cpu_offset(tmp, ri->fieldoffset); } } @@ -6426,7 +6385,7 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) /* Store a 64-bit value to a register pair. Clobbers val. */ static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val) { - TCGv tmp; + TCGv_i32 tmp; tmp = tcg_temp_new_i32(); tcg_gen_trunc_i64_i32(tmp, val); store_reg(s, rlow, tmp); @@ -6440,7 +6399,7 @@ static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val) static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow) { TCGv_i64 tmp; - TCGv tmp2; + TCGv_i32 tmp2; /* Load value and extend to 64 bits. */ tmp = tcg_temp_new_i64(); @@ -6455,8 +6414,8 @@ static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow) static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) { TCGv_i64 tmp; - TCGv tmpl; - TCGv tmph; + TCGv_i32 tmpl; + TCGv_i32 tmph; /* Load 64-bit value rd:rn. */ tmpl = load_reg(s, rlow); @@ -6470,7 +6429,7 @@ static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) } /* Set N and Z flags from hi|lo. */ -static void gen_logicq_cc(TCGv lo, TCGv hi) +static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi) { tcg_gen_mov_i32(cpu_NF, hi); tcg_gen_or_i32(cpu_ZF, lo, hi); @@ -6486,20 +6445,20 @@ static void gen_logicq_cc(TCGv lo, TCGv hi) this sequence is effectively atomic. In user emulation mode we throw an exception and handle the atomic operation elsewhere. */ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, - TCGv addr, int size) + TCGv_i32 addr, int size) { - TCGv tmp; + TCGv_i32 tmp = tcg_temp_new_i32(); switch (size) { case 0: - tmp = gen_ld8u(addr, IS_USER(s)); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); break; case 1: - tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); break; case 2: case 3: - tmp = gen_ld32(addr, IS_USER(s)); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); break; default: abort(); @@ -6507,9 +6466,10 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, tcg_gen_mov_i32(cpu_exclusive_val, tmp); store_reg(s, rt, tmp); if (size == 3) { - TCGv tmp2 = tcg_temp_new_i32(); + TCGv_i32 tmp2 = tcg_temp_new_i32(); tcg_gen_addi_i32(tmp2, addr, 4); - tmp = gen_ld32(tmp2, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, tmp2, IS_USER(s)); tcg_temp_free_i32(tmp2); tcg_gen_mov_i32(cpu_exclusive_high, tmp); store_reg(s, rt2, tmp); @@ -6524,7 +6484,7 @@ static void gen_clrex(DisasContext *s) #ifdef CONFIG_USER_ONLY static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, - TCGv addr, int size) + TCGv_i32 addr, int size) { tcg_gen_mov_i32(cpu_exclusive_test, addr); tcg_gen_movi_i32(cpu_exclusive_info, @@ -6533,9 +6493,9 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, } #else static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, - TCGv addr, int size) + TCGv_i32 addr, int size) { - TCGv tmp; + TCGv_i32 tmp; int done_label; int fail_label; @@ -6548,16 +6508,17 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, fail_label = gen_new_label(); done_label = gen_new_label(); tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label); + tmp = tcg_temp_new_i32(); switch (size) { case 0: - tmp = gen_ld8u(addr, IS_USER(s)); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); break; case 1: - tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); break; case 2: case 3: - tmp = gen_ld32(addr, IS_USER(s)); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); break; default: abort(); @@ -6565,9 +6526,10 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label); tcg_temp_free_i32(tmp); if (size == 3) { - TCGv tmp2 = tcg_temp_new_i32(); + TCGv_i32 tmp2 = tcg_temp_new_i32(); tcg_gen_addi_i32(tmp2, addr, 4); - tmp = gen_ld32(tmp2, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, tmp2, IS_USER(s)); tcg_temp_free_i32(tmp2); tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label); tcg_temp_free_i32(tmp); @@ -6575,22 +6537,24 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, tmp = load_reg(s, rt); switch (size) { case 0: - gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); break; case 1: - gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); break; case 2: case 3: - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); break; default: abort(); } + tcg_temp_free_i32(tmp); if (size == 3) { tcg_gen_addi_i32(addr, addr, 4); tmp = load_reg(s, rt2); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_gen_movi_i32(cpu_R[rd], 0); tcg_gen_br(done_label); @@ -6636,10 +6600,12 @@ static void gen_srs(DisasContext *s, } tcg_gen_addi_i32(addr, addr, offset); tmp = load_reg(s, 14); - gen_st32(tmp, addr, 0); + tcg_gen_qemu_st32(tmp, addr, 0); + tcg_temp_free_i32(tmp); tmp = load_cpu_field(spsr); tcg_gen_addi_i32(addr, addr, 4); - gen_st32(tmp, addr, 0); + tcg_gen_qemu_st32(tmp, addr, 0); + tcg_temp_free_i32(tmp); if (writeback) { switch (amode) { case 0: @@ -6668,10 +6634,10 @@ static void gen_srs(DisasContext *s, static void disas_arm_insn(CPUARMState * env, DisasContext *s) { unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; - TCGv tmp; - TCGv tmp2; - TCGv tmp3; - TCGv addr; + TCGv_i32 tmp; + TCGv_i32 tmp2; + TCGv_i32 tmp3; + TCGv_i32 addr; TCGv_i64 tmp64; insn = arm_ldl_code(env, s->pc, s->bswap_code); @@ -6782,9 +6748,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if (offset) tcg_gen_addi_i32(addr, addr, offset); /* Load PC into tmp and CPSR into tmp2. */ - tmp = gen_ld32(addr, 0); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, 0); tcg_gen_addi_i32(addr, addr, 4); - tmp2 = gen_ld32(addr, 0); + tmp2 = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ switch (i) { @@ -7084,7 +7052,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) rn = (insn >> 16) & 0xf; tmp = load_reg(s, rn); } else { - TCGV_UNUSED(tmp); + TCGV_UNUSED_I32(tmp); } rd = (insn >> 12) & 0xf; switch(op1) { @@ -7285,11 +7253,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2); } if (insn & (1 << 21)) { /* mult accumulate */ - TCGv al = load_reg(s, rn); - TCGv ah = load_reg(s, rd); + TCGv_i32 al = load_reg(s, rn); + TCGv_i32 ah = load_reg(s, rd); tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah); - tcg_temp_free(al); - tcg_temp_free(ah); + tcg_temp_free_i32(al); + tcg_temp_free_i32(ah); } if (insn & (1 << 20)) { gen_logicq_cc(tmp, tmp2); @@ -7348,7 +7316,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) abort(); } } - tcg_temp_free(addr); + tcg_temp_free_i32(addr); } else { /* SWP instruction */ rm = (insn) & 0xf; @@ -7358,13 +7326,15 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) so it is good enough. */ addr = load_reg(s, rn); tmp = load_reg(s, rm); + tmp2 = tcg_temp_new_i32(); if (insn & (1 << 22)) { - tmp2 = gen_ld8u(addr, IS_USER(s)); - gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_qemu_ld8u(tmp2, addr, IS_USER(s)); + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); } else { - tmp2 = gen_ld32(addr, IS_USER(s)); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_ld32u(tmp2, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); } + tcg_temp_free_i32(tmp); tcg_temp_free_i32(addr); store_reg(s, rd, tmp2); } @@ -7381,16 +7351,17 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) address_offset = 0; if (insn & (1 << 20)) { /* load */ + tmp = tcg_temp_new_i32(); switch(sh) { case 1: - tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); break; case 2: - tmp = gen_ld8s(addr, IS_USER(s)); + tcg_gen_qemu_ld8s(tmp, addr, IS_USER(s)); break; default: case 3: - tmp = gen_ld16s(addr, IS_USER(s)); + tcg_gen_qemu_ld16s(tmp, addr, IS_USER(s)); break; } load = 1; @@ -7400,17 +7371,21 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if (sh & 1) { /* store */ tmp = load_reg(s, rd); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); tcg_gen_addi_i32(addr, addr, 4); tmp = load_reg(s, rd + 1); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); load = 0; } else { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); store_reg(s, rd, tmp); tcg_gen_addi_i32(addr, addr, 4); - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); rd++; load = 1; } @@ -7418,7 +7393,8 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } else { /* store */ tmp = load_reg(s, rd); - gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); load = 0; } /* Perform base writeback before the loaded value to @@ -7748,18 +7724,21 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) gen_add_data_offset(s, insn, tmp2); if (insn & (1 << 20)) { /* load */ + tmp = tcg_temp_new_i32(); if (insn & (1 << 22)) { - tmp = gen_ld8u(tmp2, i); + tcg_gen_qemu_ld8u(tmp, tmp2, i); } else { - tmp = gen_ld32(tmp2, i); + tcg_gen_qemu_ld32u(tmp, tmp2, i); } } else { /* store */ tmp = load_reg(s, rd); - if (insn & (1 << 22)) - gen_st8(tmp, tmp2, i); - else - gen_st32(tmp, tmp2, i); + if (insn & (1 << 22)) { + tcg_gen_qemu_st8(tmp, tmp2, i); + } else { + tcg_gen_qemu_st32(tmp, tmp2, i); + } + tcg_temp_free_i32(tmp); } if (!(insn & (1 << 24))) { gen_add_data_offset(s, insn, tmp2); @@ -7778,7 +7757,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) case 0x09: { int j, n, user, loaded_base; - TCGv loaded_var; + TCGv_i32 loaded_var; /* load/store multiple words */ /* XXX: store correct base if write back */ user = 0; @@ -7794,7 +7773,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) /* compute total size */ loaded_base = 0; - TCGV_UNUSED(loaded_var); + TCGV_UNUSED_I32(loaded_var); n = 0; for(i=0;i<16;i++) { if (insn & (1 << i)) @@ -7823,7 +7802,8 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if (insn & (1 << i)) { if (insn & (1 << 20)) { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); if (user) { tmp2 = tcg_const_i32(i); gen_helper_set_user_reg(cpu_env, tmp2, tmp); @@ -7850,7 +7830,8 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } else { tmp = load_reg(s, i); } - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } j++; /* no need to add after the last transfer */ @@ -7944,7 +7925,8 @@ thumb2_logic_op(int op) Returns zero if the opcode is valid. */ static int -gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1) +gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, + TCGv_i32 t0, TCGv_i32 t1) { int logic_cc; @@ -8018,10 +8000,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw { uint32_t insn, imm, shift, offset; uint32_t rd, rn, rm, rs; - TCGv tmp; - TCGv tmp2; - TCGv tmp3; - TCGv addr; + TCGv_i32 tmp; + TCGv_i32 tmp2; + TCGv_i32 tmp3; + TCGv_i32 addr; TCGv_i64 tmp64; int op; int shiftop; @@ -8106,18 +8088,22 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } if (insn & (1 << 20)) { /* ldrd */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); store_reg(s, rs, tmp); tcg_gen_addi_i32(addr, addr, 4); - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); store_reg(s, rd, tmp); } else { /* strd */ tmp = load_reg(s, rs); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); tcg_gen_addi_i32(addr, addr, 4); tmp = load_reg(s, rd); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } if (insn & (1 << 21)) { /* Base writeback. */ @@ -8130,7 +8116,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } } else if ((insn & (1 << 23)) == 0) { /* Load/store exclusive word. */ - addr = tcg_temp_local_new(); + addr = tcg_temp_local_new_i32(); load_reg_var(s, addr, rn); tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2); if (insn & (1 << 20)) { @@ -8138,7 +8124,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } else { gen_store_exclusive(s, rd, rs, 15, addr, 2); } - tcg_temp_free(addr); + tcg_temp_free_i32(addr); } else if ((insn & (1 << 6)) == 0) { /* Table Branch. */ if (rn == 15) { @@ -8153,10 +8139,12 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw /* tbh */ tcg_gen_add_i32(addr, addr, tmp); tcg_temp_free_i32(tmp); - tmp = gen_ld16u(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); } else { /* tbb */ tcg_temp_free_i32(tmp); - tmp = gen_ld8u(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); } tcg_temp_free_i32(addr); tcg_gen_shli_i32(tmp, tmp, 1); @@ -8169,14 +8157,14 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw if (op == 2) { goto illegal_op; } - addr = tcg_temp_local_new(); + addr = tcg_temp_local_new_i32(); load_reg_var(s, addr, rn); if (insn & (1 << 20)) { gen_load_exclusive(s, rs, rd, addr, op); } else { gen_store_exclusive(s, rm, rs, rd, addr, op); } - tcg_temp_free(addr); + tcg_temp_free_i32(addr); } } else { /* Load/store multiple, RFE, SRS. */ @@ -8191,9 +8179,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw if ((insn & (1 << 24)) == 0) tcg_gen_addi_i32(addr, addr, -8); /* Load PC into tmp and CPSR into tmp2. */ - tmp = gen_ld32(addr, 0); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, 0); tcg_gen_addi_i32(addr, addr, 4); - tmp2 = gen_ld32(addr, 0); + tmp2 = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp2, addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ if (insn & (1 << 24)) { @@ -8213,7 +8203,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } } else { int i, loaded_base = 0; - TCGv loaded_var; + TCGv_i32 loaded_var; /* Load/store multiple. */ addr = load_reg(s, rn); offset = 0; @@ -8225,13 +8215,14 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw tcg_gen_addi_i32(addr, addr, -offset); } - TCGV_UNUSED(loaded_var); + TCGV_UNUSED_I32(loaded_var); for (i = 0; i < 16; i++) { if ((insn & (1 << i)) == 0) continue; if (insn & (1 << 20)) { /* Load. */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); if (i == 15) { gen_bx(s, tmp); } else if (i == rn) { @@ -8243,7 +8234,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } else { /* Store. */ tmp = load_reg(s, i); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_gen_addi_i32(addr, addr, 4); } @@ -9015,13 +9007,25 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } if (insn & (1 << 20)) { /* Load. */ + tmp = tcg_temp_new_i32(); switch (op) { - case 0: tmp = gen_ld8u(addr, user); break; - case 4: tmp = gen_ld8s(addr, user); break; - case 1: tmp = gen_ld16u(addr, user); break; - case 5: tmp = gen_ld16s(addr, user); break; - case 2: tmp = gen_ld32(addr, user); break; + case 0: + tcg_gen_qemu_ld8u(tmp, addr, user); + break; + case 4: + tcg_gen_qemu_ld8s(tmp, addr, user); + break; + case 1: + tcg_gen_qemu_ld16u(tmp, addr, user); + break; + case 5: + tcg_gen_qemu_ld16s(tmp, addr, user); + break; + case 2: + tcg_gen_qemu_ld32u(tmp, addr, user); + break; default: + tcg_temp_free_i32(tmp); tcg_temp_free_i32(addr); goto illegal_op; } @@ -9034,13 +9038,21 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw /* Store. */ tmp = load_reg(s, rs); switch (op) { - case 0: gen_st8(tmp, addr, user); break; - case 1: gen_st16(tmp, addr, user); break; - case 2: gen_st32(tmp, addr, user); break; + case 0: + tcg_gen_qemu_st8(tmp, addr, user); + break; + case 1: + tcg_gen_qemu_st16(tmp, addr, user); + break; + case 2: + tcg_gen_qemu_st32(tmp, addr, user); + break; default: + tcg_temp_free_i32(tmp); tcg_temp_free_i32(addr); goto illegal_op; } + tcg_temp_free_i32(tmp); } if (postinc) tcg_gen_addi_i32(addr, addr, imm); @@ -9064,9 +9076,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) uint32_t val, insn, op, rm, rn, rd, shift, cond; int32_t offset; int i; - TCGv tmp; - TCGv tmp2; - TCGv addr; + TCGv_i32 tmp; + TCGv_i32 tmp2; + TCGv_i32 addr; if (s->condexec_mask) { cond = s->condexec_cond; @@ -9169,7 +9181,8 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) val &= ~(uint32_t)2; addr = tcg_temp_new_i32(); tcg_gen_movi_i32(addr, val); - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); tcg_temp_free_i32(addr); store_reg(s, rd, tmp); break; @@ -9234,7 +9247,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) } else if (op != 0xf) { /* mvn doesn't read its first operand */ tmp = load_reg(s, rd); } else { - TCGV_UNUSED(tmp); + TCGV_UNUSED_I32(tmp); } tmp2 = load_reg(s, rm); @@ -9364,37 +9377,43 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) tcg_gen_add_i32(addr, addr, tmp); tcg_temp_free_i32(tmp); - if (op < 3) /* store */ + if (op < 3) { /* store */ tmp = load_reg(s, rd); + } else { + tmp = tcg_temp_new_i32(); + } switch (op) { case 0: /* str */ - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); break; case 1: /* strh */ - gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); break; case 2: /* strb */ - gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); break; case 3: /* ldrsb */ - tmp = gen_ld8s(addr, IS_USER(s)); + tcg_gen_qemu_ld8s(tmp, addr, IS_USER(s)); break; case 4: /* ldr */ - tmp = gen_ld32(addr, IS_USER(s)); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); break; case 5: /* ldrh */ - tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); break; case 6: /* ldrb */ - tmp = gen_ld8u(addr, IS_USER(s)); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); break; case 7: /* ldrsh */ - tmp = gen_ld16s(addr, IS_USER(s)); + tcg_gen_qemu_ld16s(tmp, addr, IS_USER(s)); break; } - if (op >= 3) /* load */ + if (op >= 3) { /* load */ store_reg(s, rd, tmp); + } else { + tcg_temp_free_i32(tmp); + } tcg_temp_free_i32(addr); break; @@ -9408,12 +9427,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (insn & (1 << 11)) { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); store_reg(s, rd, tmp); } else { /* store */ tmp = load_reg(s, rd); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; @@ -9428,12 +9449,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (insn & (1 << 11)) { /* load */ - tmp = gen_ld8u(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); store_reg(s, rd, tmp); } else { /* store */ tmp = load_reg(s, rd); - gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; @@ -9448,12 +9471,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (insn & (1 << 11)) { /* load */ - tmp = gen_ld16u(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); store_reg(s, rd, tmp); } else { /* store */ tmp = load_reg(s, rd); - gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; @@ -9467,12 +9492,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (insn & (1 << 11)) { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); store_reg(s, rd, tmp); } else { /* store */ tmp = load_reg(s, rd); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; @@ -9538,28 +9565,32 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (insn & (1 << i)) { if (insn & (1 << 11)) { /* pop */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); store_reg(s, i, tmp); } else { /* push */ tmp = load_reg(s, i); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } /* advance to the next address. */ tcg_gen_addi_i32(addr, addr, 4); } } - TCGV_UNUSED(tmp); + TCGV_UNUSED_I32(tmp); if (insn & (1 << 8)) { if (insn & (1 << 11)) { /* pop pc */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); /* don't set the pc until the rest of the instruction has completed */ } else { /* push lr */ tmp = load_reg(s, 14); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } tcg_gen_addi_i32(addr, addr, 4); } @@ -9674,15 +9705,16 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) case 12: { /* load/store multiple */ - TCGv loaded_var; - TCGV_UNUSED(loaded_var); + TCGv_i32 loaded_var; + TCGV_UNUSED_I32(loaded_var); rn = (insn >> 8) & 0x7; addr = load_reg(s, rn); for (i = 0; i < 8; i++) { if (insn & (1 << i)) { if (insn & (1 << 11)) { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = tcg_temp_new_i32(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); if (i == rn) { loaded_var = tmp; } else { @@ -9691,7 +9723,8 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) } else { /* store */ tmp = load_reg(s, i); - gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + tcg_temp_free_i32(tmp); } /* advance to the next address */ tcg_gen_addi_i32(addr, addr, 4); @@ -9851,7 +9884,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env, complications trying to do it at the end of the block. */ if (dc->condexec_mask || dc->condexec_cond) { - TCGv tmp = tcg_temp_new_i32(); + TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, 0); store_cpu_field(tmp, condexec_bits); } diff --git a/target-mips/cpu.h b/target-mips/cpu.h index cedf03df43..6e761e03b6 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -668,6 +668,7 @@ void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra); hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, int rw); #endif +target_ulong exception_resume_pc (CPUMIPSState *env); static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, target_ulong *cs_base, int *flags) diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c index 918a898699..4116de93c3 100644 --- a/target-mips/dsp_helper.c +++ b/target-mips/dsp_helper.c @@ -2902,13 +2902,13 @@ target_ulong helper_bitrev(target_ulong rt) return (target_ulong)rd; } -#define BIT_INSV(name, posfilter, sizefilter, ret_type) \ +#define BIT_INSV(name, posfilter, ret_type) \ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \ target_ulong rt) \ { \ uint32_t pos, size, msb, lsb; \ - target_ulong filter; \ - target_ulong temp, temprs, temprt; \ + uint32_t const sizefilter = 0x3F; \ + target_ulong temp; \ target_ulong dspc; \ \ dspc = env->active_tc.DSPControl; \ @@ -2923,18 +2923,14 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \ return rt; \ } \ \ - filter = ((int64_t)0x01 << size) - 1; \ - filter = filter << pos; \ - temprs = (rs << pos) & filter; \ - temprt = rt & ~filter; \ - temp = temprs | temprt; \ + temp = deposit64(rt, pos, size, rs); \ \ return (target_long)(ret_type)temp; \ } -BIT_INSV(insv, 0x1F, 0x3F, int32_t); +BIT_INSV(insv, 0x1F, int32_t); #ifdef TARGET_MIPS64 -BIT_INSV(dinsv, 0x7F, 0x3F, target_long); +BIT_INSV(dinsv, 0x7F, target_long); #endif #undef BIT_INSV diff --git a/target-mips/helper.c b/target-mips/helper.c index 3a54acf706..36929ddee7 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -366,8 +366,7 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_CACHE] = "cache error", }; -#if !defined(CONFIG_USER_ONLY) -static target_ulong exception_resume_pc (CPUMIPSState *env) +target_ulong exception_resume_pc (CPUMIPSState *env) { target_ulong bad_pc; target_ulong isa_mode; @@ -383,6 +382,7 @@ static target_ulong exception_resume_pc (CPUMIPSState *env) return bad_pc; } +#if !defined(CONFIG_USER_ONLY) static void set_hflags_for_handler (CPUMIPSState *env) { /* Exception handlers are entered in 32-bit mode. */ diff --git a/target-moxie/helper.c b/target-moxie/helper.c index 6e0ac2aa2a..5cfe889ad4 100644 --- a/target-moxie/helper.c +++ b/target-moxie/helper.c @@ -116,7 +116,7 @@ int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address, return 1; } -target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) +hwaddr cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { return addr; } diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 725071e6a7..3ab2946cfb 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -30,8 +30,6 @@ #include "cpu.h" #include "sysemu/cpus.h" #include "sysemu/device_tree.h" -#include "hw/sysbus.h" -#include "hw/ppc/spapr.h" #include "mmu-hash64.h" #include "hw/sysbus.h" diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 0ce82cf830..6304c4d90b 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -34,7 +34,10 @@ #include "exec/cpu-defs.h" #define TARGET_PAGE_BITS 12 -#define TARGET_PHYS_ADDR_SPACE_BITS 64 +/* Actually 64-bits, limited by the memory API to 62 bits. We + * never use that much. + */ +#define TARGET_PHYS_ADDR_SPACE_BITS 62 #define TARGET_VIRT_ADDR_SPACE_BITS 64 #include "exec/cpu-all.h" diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c index ab1adfd7ea..290b5809aa 100644 --- a/target-sparc/cpu.c +++ b/target-sparc/cpu.c @@ -292,19 +292,6 @@ static const sparc_def_t sparc_defs[] = { }, #else { - .name = "Fujitsu MB86900", - .iu_version = 0x00 << 24, /* Impl 0, ver 0 */ - .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ - .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */ - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 7, - .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD, - }, - { .name = "Fujitsu MB86904", .iu_version = 0x04 << 24, /* Impl 0, ver 4 */ .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ @@ -331,48 +318,6 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "LSI L64811", - .iu_version = 0x10 << 24, /* Impl 1, ver 0 */ - .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */ - .mmu_version = 0x10 << 24, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | - CPU_FEATURE_FSMULD, - }, - { - .name = "Cypress CY7C601", - .iu_version = 0x11 << 24, /* Impl 1, ver 1 */ - .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */ - .mmu_version = 0x10 << 24, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | - CPU_FEATURE_FSMULD, - }, - { - .name = "Cypress CY7C611", - .iu_version = 0x13 << 24, /* Impl 1, ver 3 */ - .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */ - .mmu_version = 0x10 << 24, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | - CPU_FEATURE_FSMULD, - }, - { .name = "TI MicroSparc I", .iu_version = 0x41000000, .fpu_version = 4 << 17, @@ -495,73 +440,6 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Ross RT625", - .iu_version = 0x1e000000, - .fpu_version = 1 << 17, - .mmu_version = 0x1e000000, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_DEFAULT_FEATURES, - }, - { - .name = "Ross RT620", - .iu_version = 0x1f000000, - .fpu_version = 1 << 17, - .mmu_version = 0x1f000000, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_DEFAULT_FEATURES, - }, - { - .name = "BIT B5010", - .iu_version = 0x20000000, - .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */ - .mmu_version = 0x20000000, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT | - CPU_FEATURE_FSMULD, - }, - { - .name = "Matsushita MN10501", - .iu_version = 0x50000000, - .fpu_version = 0 << 17, - .mmu_version = 0x50000000, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT | - CPU_FEATURE_FSMULD, - }, - { - .name = "Weitek W8601", - .iu_version = 0x90 << 24, /* Impl 9, ver 0 */ - .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */ - .mmu_version = 0x10 << 24, - .mmu_bm = 0x00004000, - .mmu_ctpr_mask = 0x007ffff0, - .mmu_cxr_mask = 0x0000003f, - .mmu_sfsr_mask = 0xffffffff, - .mmu_trcr_mask = 0xffffffff, - .nwindows = 8, - .features = CPU_DEFAULT_FEATURES, - }, - { .name = "LEON2", .iu_version = 0xf2000000, .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */ diff --git a/tests/qemu-iotests/054 b/tests/qemu-iotests/054 new file mode 100755 index 0000000000..b36042958c --- /dev/null +++ b/tests/qemu-iotests/054 @@ -0,0 +1,58 @@ +#!/bin/bash +# +# Test huge qcow2 images +# +# Copyright (C) 2013 Red Hat, Inc. +# +# 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/>. +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + +echo +echo "creating too large image (1 EB)" +_make_test_img $((1024*1024))T + +echo +echo "creating too large image (1 EB) using qcow2.py" +_make_test_img 4G +./qcow2.py $TEST_IMG set-header size $((1024 ** 6)) +_check_test_img + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/054.out b/tests/qemu-iotests/054.out new file mode 100644 index 0000000000..0b2fe301ea --- /dev/null +++ b/tests/qemu-iotests/054.out @@ -0,0 +1,10 @@ +QA output created by 054 + +creating too large image (1 EB) +qemu-img: The image size is too large for file format 'qcow2' +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1152921504606846976 + +creating too large image (1 EB) using qcow2.py +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 +qemu-img: Could not open 'TEST_DIR/t.qcow2': File too large +*** done diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 31eb62b604..e9ba3586b5 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -167,7 +167,7 @@ _cleanup_test_img() _check_test_img() { - $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | \ + $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | _filter_testdir | \ sed -e '/allocated.*fragmented.*compressed clusters/d' \ -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \ -e '/Image end offset: [0-9]\+/d' diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index bf944d9123..387b050987 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -60,3 +60,4 @@ #051 rw auto 052 rw auto backing 053 rw auto +054 rw auto diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index fecf5b9a59..44a2b45641 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -149,6 +149,22 @@ def cmd_dump_header(fd): h.dump() h.dump_extensions() +def cmd_set_header(fd, name, value): + try: + value = int(value, 0) + except: + print "'%s' is not a valid number" % value + sys.exit(1) + + fields = (field[2] for field in QcowHeader.fields) + if not name in fields: + print "'%s' is not a known header field" % name + sys.exit(1) + + h = QcowHeader(fd) + h.__dict__[name] = value + h.update(fd) + def cmd_add_header_ext(fd, magic, data): try: magic = int(magic, 0) @@ -205,6 +221,7 @@ def cmd_set_feature_bit(fd, group, bit): cmds = [ [ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ], + [ 'set-header', cmd_set_header, 2, 'Set a field in the header'], [ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ], [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ], [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'], diff --git a/tests/tcg/linux-test.c b/tests/tcg/linux-test.c index 83cb32ddb9..1c6c01318e 100644 --- a/tests/tcg/linux-test.c +++ b/tests/tcg/linux-test.c @@ -39,7 +39,6 @@ #include <dirent.h> #include <setjmp.h> #include <sys/shm.h> -#include <sched.h> #define TESTPATH "/tmp/linux-test.tmp" #define TESTPORT 7654 diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 955a4c0b0a..2741eef3fa 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -61,6 +61,31 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data, return v; } +/* similar to visitor_input_test_init(), but does not expect a string + * literal/format json_string argument and so can be used for + * programatically generated strings (and we can't pass in programatically + * generated strings via %s format parameters since qobject_from_jsonv() + * will wrap those in double-quotes and treat the entire object as a + * string) + */ +static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data, + const char *json_string) +{ + Visitor *v; + + data->obj = qobject_from_json(json_string); + + g_assert(data->obj != NULL); + + data->qiv = qmp_input_visitor_new(data->obj); + g_assert(data->qiv != NULL); + + v = qmp_input_get_visitor(data->qiv); + g_assert(v != NULL); + + return v; +} + static void test_visitor_in_int(TestInputVisitorData *data, const void *unused) { @@ -75,6 +100,24 @@ static void test_visitor_in_int(TestInputVisitorData *data, g_assert_cmpint(res, ==, value); } +static void test_visitor_in_int_overflow(TestInputVisitorData *data, + const void *unused) +{ + int64_t res = 0; + Error *errp = NULL; + Visitor *v; + + /* this will overflow a Qint/int64, so should be deserialized into + * a QFloat/double field instead, leading to an error if we pass it + * to visit_type_int. confirm this. + */ + v = visitor_input_test_init(data, "%f", DBL_MAX); + + visit_type_int(v, &res, NULL, &errp); + g_assert(error_is_set(&errp)); + error_free(errp); +} + static void test_visitor_in_bool(TestInputVisitorData *data, const void *unused) { @@ -259,6 +302,287 @@ static void test_visitor_in_union(TestInputVisitorData *data, qapi_free_UserDefUnion(tmp); } +static void test_native_list_integer_helper(TestInputVisitorData *data, + const void *unused, + UserDefNativeListUnionKind kind) +{ + UserDefNativeListUnion *cvalue = NULL; + Error *err = NULL; + Visitor *v; + GString *gstr_list = g_string_new(""); + GString *gstr_union = g_string_new(""); + int i; + + for (i = 0; i < 32; i++) { + g_string_append_printf(gstr_list, "%d", i); + if (i != 31) { + g_string_append(gstr_list, ", "); + } + } + g_string_append_printf(gstr_union, "{ 'type': '%s', 'data': [ %s ] }", + UserDefNativeListUnionKind_lookup[kind], + gstr_list->str); + v = visitor_input_test_init_raw(data, gstr_union->str); + + visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); + g_assert(err == NULL); + g_assert(cvalue != NULL); + g_assert_cmpint(cvalue->kind, ==, kind); + + switch (kind) { + case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: { + intList *elem = NULL; + for (i = 0, elem = cvalue->integer; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S8: { + int8List *elem = NULL; + for (i = 0, elem = cvalue->s8; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S16: { + int16List *elem = NULL; + for (i = 0, elem = cvalue->s16; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S32: { + int32List *elem = NULL; + for (i = 0, elem = cvalue->s32; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S64: { + int64List *elem = NULL; + for (i = 0, elem = cvalue->s64; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U8: { + uint8List *elem = NULL; + for (i = 0, elem = cvalue->u8; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U16: { + uint16List *elem = NULL; + for (i = 0, elem = cvalue->u16; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U32: { + uint32List *elem = NULL; + for (i = 0, elem = cvalue->u32; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U64: { + uint64List *elem = NULL; + for (i = 0, elem = cvalue->u64; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, i); + } + break; + } + default: + g_assert(false); + } + + g_string_free(gstr_union, true); + g_string_free(gstr_list, true); + qapi_free_UserDefNativeListUnion(cvalue); +} + +static void test_visitor_in_native_list_int(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER); +} + +static void test_visitor_in_native_list_int8(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_S8); +} + +static void test_visitor_in_native_list_int16(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_S16); +} + +static void test_visitor_in_native_list_int32(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_S32); +} + +static void test_visitor_in_native_list_int64(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_S64); +} + +static void test_visitor_in_native_list_uint8(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_U8); +} + +static void test_visitor_in_native_list_uint16(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_U16); +} + +static void test_visitor_in_native_list_uint32(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_U32); +} + +static void test_visitor_in_native_list_uint64(TestInputVisitorData *data, + const void *unused) +{ + test_native_list_integer_helper(data, unused, + USER_DEF_NATIVE_LIST_UNION_KIND_U64); +} + +static void test_visitor_in_native_list_bool(TestInputVisitorData *data, + const void *unused) +{ + UserDefNativeListUnion *cvalue = NULL; + boolList *elem = NULL; + Error *err = NULL; + Visitor *v; + GString *gstr_list = g_string_new(""); + GString *gstr_union = g_string_new(""); + int i; + + for (i = 0; i < 32; i++) { + g_string_append_printf(gstr_list, "%s", + (i % 3 == 0) ? "true" : "false"); + if (i != 31) { + g_string_append(gstr_list, ", "); + } + } + g_string_append_printf(gstr_union, "{ 'type': 'boolean', 'data': [ %s ] }", + gstr_list->str); + v = visitor_input_test_init_raw(data, gstr_union->str); + + visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); + g_assert(err == NULL); + g_assert(cvalue != NULL); + g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN); + + for (i = 0, elem = cvalue->boolean; elem; elem = elem->next, i++) { + g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0); + } + + g_string_free(gstr_union, true); + g_string_free(gstr_list, true); + qapi_free_UserDefNativeListUnion(cvalue); +} + +static void test_visitor_in_native_list_string(TestInputVisitorData *data, + const void *unused) +{ + UserDefNativeListUnion *cvalue = NULL; + strList *elem = NULL; + Error *err = NULL; + Visitor *v; + GString *gstr_list = g_string_new(""); + GString *gstr_union = g_string_new(""); + int i; + + for (i = 0; i < 32; i++) { + g_string_append_printf(gstr_list, "'%d'", i); + if (i != 31) { + g_string_append(gstr_list, ", "); + } + } + g_string_append_printf(gstr_union, "{ 'type': 'string', 'data': [ %s ] }", + gstr_list->str); + v = visitor_input_test_init_raw(data, gstr_union->str); + + visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); + g_assert(err == NULL); + g_assert(cvalue != NULL); + g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING); + + for (i = 0, elem = cvalue->string; elem; elem = elem->next, i++) { + gchar str[8]; + sprintf(str, "%d", i); + g_assert_cmpstr(elem->value, ==, str); + } + + g_string_free(gstr_union, true); + g_string_free(gstr_list, true); + qapi_free_UserDefNativeListUnion(cvalue); +} + +#define DOUBLE_STR_MAX 16 + +static void test_visitor_in_native_list_number(TestInputVisitorData *data, + const void *unused) +{ + UserDefNativeListUnion *cvalue = NULL; + numberList *elem = NULL; + Error *err = NULL; + Visitor *v; + GString *gstr_list = g_string_new(""); + GString *gstr_union = g_string_new(""); + int i; + + for (i = 0; i < 32; i++) { + g_string_append_printf(gstr_list, "%f", (double)i / 3); + if (i != 31) { + g_string_append(gstr_list, ", "); + } + } + g_string_append_printf(gstr_union, "{ 'type': 'number', 'data': [ %s ] }", + gstr_list->str); + v = visitor_input_test_init_raw(data, gstr_union->str); + + visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); + g_assert(err == NULL); + g_assert(cvalue != NULL); + g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER); + + for (i = 0, elem = cvalue->number; elem; elem = elem->next, i++) { + GString *double_expected = g_string_new(""); + GString *double_actual = g_string_new(""); + + g_string_printf(double_expected, "%.6f", (double)i / 3); + g_string_printf(double_actual, "%.6f", elem->value); + g_assert_cmpstr(double_expected->str, ==, double_actual->str); + + g_string_free(double_expected, true); + g_string_free(double_actual, true); + } + + g_string_free(gstr_union, true); + g_string_free(gstr_list, true); + qapi_free_UserDefNativeListUnion(cvalue); +} + static void input_visitor_test_add(const char *testpath, TestInputVisitorData *data, void (*test_func)(TestInputVisitorData *data, const void *user_data)) @@ -292,6 +616,8 @@ int main(int argc, char **argv) input_visitor_test_add("/visitor/input/int", &in_visitor_data, test_visitor_in_int); + input_visitor_test_add("/visitor/input/int_overflow", + &in_visitor_data, test_visitor_in_int_overflow); input_visitor_test_add("/visitor/input/bool", &in_visitor_data, test_visitor_in_bool); input_visitor_test_add("/visitor/input/number", @@ -310,6 +636,38 @@ int main(int argc, char **argv) &in_visitor_data, test_visitor_in_union); input_visitor_test_add("/visitor/input/errors", &in_visitor_data, test_visitor_in_errors); + input_visitor_test_add("/visitor/input/native_list/int", + &in_visitor_data, + test_visitor_in_native_list_int); + input_visitor_test_add("/visitor/input/native_list/int8", + &in_visitor_data, + test_visitor_in_native_list_int8); + input_visitor_test_add("/visitor/input/native_list/int16", + &in_visitor_data, + test_visitor_in_native_list_int16); + input_visitor_test_add("/visitor/input/native_list/int32", + &in_visitor_data, + test_visitor_in_native_list_int32); + input_visitor_test_add("/visitor/input/native_list/int64", + &in_visitor_data, + test_visitor_in_native_list_int64); + input_visitor_test_add("/visitor/input/native_list/uint8", + &in_visitor_data, + test_visitor_in_native_list_uint8); + input_visitor_test_add("/visitor/input/native_list/uint16", + &in_visitor_data, + test_visitor_in_native_list_uint16); + input_visitor_test_add("/visitor/input/native_list/uint32", + &in_visitor_data, + test_visitor_in_native_list_uint32); + input_visitor_test_add("/visitor/input/native_list/uint64", + &in_visitor_data, test_visitor_in_native_list_uint64); + input_visitor_test_add("/visitor/input/native_list/bool", + &in_visitor_data, test_visitor_in_native_list_bool); + input_visitor_test_add("/visitor/input/native_list/str", + &in_visitor_data, test_visitor_in_native_list_string); + input_visitor_test_add("/visitor/input/native_list/number", + &in_visitor_data, test_visitor_in_native_list_number); g_test_run(); diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index 71367e6efa..0942a41875 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -431,6 +431,314 @@ static void test_visitor_out_union(TestOutputVisitorData *data, QDECREF(qdict); } +static void init_native_list(UserDefNativeListUnion *cvalue) +{ + int i; + switch (cvalue->kind) { + case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: { + intList **list = &cvalue->integer; + for (i = 0; i < 32; i++) { + *list = g_new0(intList, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S8: { + int8List **list = &cvalue->s8; + for (i = 0; i < 32; i++) { + *list = g_new0(int8List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S16: { + int16List **list = &cvalue->s16; + for (i = 0; i < 32; i++) { + *list = g_new0(int16List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S32: { + int32List **list = &cvalue->s32; + for (i = 0; i < 32; i++) { + *list = g_new0(int32List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_S64: { + int64List **list = &cvalue->s64; + for (i = 0; i < 32; i++) { + *list = g_new0(int64List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U8: { + uint8List **list = &cvalue->u8; + for (i = 0; i < 32; i++) { + *list = g_new0(uint8List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U16: { + uint16List **list = &cvalue->u16; + for (i = 0; i < 32; i++) { + *list = g_new0(uint16List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U32: { + uint32List **list = &cvalue->u32; + for (i = 0; i < 32; i++) { + *list = g_new0(uint32List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_U64: { + uint64List **list = &cvalue->u64; + for (i = 0; i < 32; i++) { + *list = g_new0(uint64List, 1); + (*list)->value = i; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: { + boolList **list = &cvalue->boolean; + for (i = 0; i < 32; i++) { + *list = g_new0(boolList, 1); + (*list)->value = (i % 3 == 0); + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: { + strList **list = &cvalue->string; + for (i = 0; i < 32; i++) { + *list = g_new0(strList, 1); + (*list)->value = g_strdup_printf("%d", i); + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: { + numberList **list = &cvalue->number; + for (i = 0; i < 32; i++) { + *list = g_new0(numberList, 1); + (*list)->value = (double)i / 3; + (*list)->next = NULL; + list = &(*list)->next; + } + break; + } + default: + g_assert(false); + } +} + +static void check_native_list(QObject *qobj, + UserDefNativeListUnionKind kind) +{ + QDict *qdict; + QList *qlist; + int i; + + g_assert(qobj); + g_assert(qobject_type(qobj) == QTYPE_QDICT); + qdict = qobject_to_qdict(qobj); + g_assert(qdict); + g_assert(qdict_haskey(qdict, "data")); + qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data"))); + + switch (kind) { + case USER_DEF_NATIVE_LIST_UNION_KIND_S8: + case USER_DEF_NATIVE_LIST_UNION_KIND_S16: + case USER_DEF_NATIVE_LIST_UNION_KIND_S32: + case USER_DEF_NATIVE_LIST_UNION_KIND_S64: + case USER_DEF_NATIVE_LIST_UNION_KIND_U8: + case USER_DEF_NATIVE_LIST_UNION_KIND_U16: + case USER_DEF_NATIVE_LIST_UNION_KIND_U32: + case USER_DEF_NATIVE_LIST_UNION_KIND_U64: + /* all integer elements in JSON arrays get stored into QInts when + * we convert to QObjects, so we can check them all in the same + * fashion, so simply fall through here + */ + case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: + for (i = 0; i < 32; i++) { + QObject *tmp; + QInt *qvalue; + tmp = qlist_peek(qlist); + g_assert(tmp); + qvalue = qobject_to_qint(tmp); + g_assert_cmpint(qint_get_int(qvalue), ==, i); + qobject_decref(qlist_pop(qlist)); + } + break; + case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: + for (i = 0; i < 32; i++) { + QObject *tmp; + QBool *qvalue; + tmp = qlist_peek(qlist); + g_assert(tmp); + qvalue = qobject_to_qbool(tmp); + g_assert_cmpint(qbool_get_int(qvalue), ==, (i % 3 == 0) ? 1 : 0); + qobject_decref(qlist_pop(qlist)); + } + break; + case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: + for (i = 0; i < 32; i++) { + QObject *tmp; + QString *qvalue; + gchar str[8]; + tmp = qlist_peek(qlist); + g_assert(tmp); + qvalue = qobject_to_qstring(tmp); + sprintf(str, "%d", i); + g_assert_cmpstr(qstring_get_str(qvalue), ==, str); + qobject_decref(qlist_pop(qlist)); + } + break; + case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: + for (i = 0; i < 32; i++) { + QObject *tmp; + QFloat *qvalue; + GString *double_expected = g_string_new(""); + GString *double_actual = g_string_new(""); + + tmp = qlist_peek(qlist); + g_assert(tmp); + qvalue = qobject_to_qfloat(tmp); + g_string_printf(double_expected, "%.6f", (double)i / 3); + g_string_printf(double_actual, "%.6f", qfloat_get_double(qvalue)); + g_assert_cmpstr(double_actual->str, ==, double_expected->str); + + qobject_decref(qlist_pop(qlist)); + g_string_free(double_expected, true); + g_string_free(double_actual, true); + } + break; + default: + g_assert(false); + } + QDECREF(qlist); +} + +static void test_native_list(TestOutputVisitorData *data, + const void *unused, + UserDefNativeListUnionKind kind) +{ + UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1); + Error *err = NULL; + QObject *obj; + + cvalue->kind = kind; + init_native_list(cvalue); + + visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err); + g_assert(err == NULL); + + obj = qmp_output_get_qobject(data->qov); + check_native_list(obj, cvalue->kind); + qapi_free_UserDefNativeListUnion(cvalue); + qobject_decref(obj); +} + +static void test_visitor_out_native_list_int(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER); +} + +static void test_visitor_out_native_list_int8(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S8); +} + +static void test_visitor_out_native_list_int16(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S16); +} + +static void test_visitor_out_native_list_int32(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S32); +} + +static void test_visitor_out_native_list_int64(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S64); +} + +static void test_visitor_out_native_list_uint8(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U8); +} + +static void test_visitor_out_native_list_uint16(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U16); +} + +static void test_visitor_out_native_list_uint32(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U32); +} + +static void test_visitor_out_native_list_uint64(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U64); +} + +static void test_visitor_out_native_list_bool(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN); +} + +static void test_visitor_out_native_list_str(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_STRING); +} + +static void test_visitor_out_native_list_number(TestOutputVisitorData *data, + const void *unused) +{ + test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER); +} + static void output_visitor_test_add(const char *testpath, TestOutputVisitorData *data, void (*test_func)(TestOutputVisitorData *data, const void *user_data)) @@ -471,6 +779,30 @@ int main(int argc, char **argv) &out_visitor_data, test_visitor_out_list_qapi_free); output_visitor_test_add("/visitor/output/union", &out_visitor_data, test_visitor_out_union); + output_visitor_test_add("/visitor/output/native_list/int", + &out_visitor_data, test_visitor_out_native_list_int); + output_visitor_test_add("/visitor/output/native_list/int8", + &out_visitor_data, test_visitor_out_native_list_int8); + output_visitor_test_add("/visitor/output/native_list/int16", + &out_visitor_data, test_visitor_out_native_list_int16); + output_visitor_test_add("/visitor/output/native_list/int32", + &out_visitor_data, test_visitor_out_native_list_int32); + output_visitor_test_add("/visitor/output/native_list/int64", + &out_visitor_data, test_visitor_out_native_list_int64); + output_visitor_test_add("/visitor/output/native_list/uint8", + &out_visitor_data, test_visitor_out_native_list_uint8); + output_visitor_test_add("/visitor/output/native_list/uint16", + &out_visitor_data, test_visitor_out_native_list_uint16); + output_visitor_test_add("/visitor/output/native_list/uint32", + &out_visitor_data, test_visitor_out_native_list_uint32); + output_visitor_test_add("/visitor/output/native_list/uint64", + &out_visitor_data, test_visitor_out_native_list_uint64); + output_visitor_test_add("/visitor/output/native_list/bool", + &out_visitor_data, test_visitor_out_native_list_bool); + output_visitor_test_add("/visitor/output/native_list/string", + &out_visitor_data, test_visitor_out_native_list_str); + output_visitor_test_add("/visitor/output/native_list/number", + &out_visitor_data, test_visitor_out_native_list_number); g_test_run(); diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c index 8c8adac6a9..ee7916b806 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -23,6 +23,25 @@ #include "qapi/qmp-output-visitor.h" #include "qapi/string-input-visitor.h" #include "qapi/string-output-visitor.h" +#include "qapi-types.h" +#include "qapi-visit.h" +#include "qapi/dealloc-visitor.h" + +enum PrimitiveTypeKind { + PTYPE_STRING = 0, + PTYPE_BOOLEAN, + PTYPE_NUMBER, + PTYPE_INTEGER, + PTYPE_U8, + PTYPE_U16, + PTYPE_U32, + PTYPE_U64, + PTYPE_S8, + PTYPE_S16, + PTYPE_S32, + PTYPE_S64, + PTYPE_EOL, +}; typedef struct PrimitiveType { union { @@ -40,26 +59,42 @@ typedef struct PrimitiveType { int64_t s64; intmax_t max; } value; - enum { - PTYPE_STRING = 0, - PTYPE_BOOLEAN, - PTYPE_NUMBER, - PTYPE_INTEGER, - PTYPE_U8, - PTYPE_U16, - PTYPE_U32, - PTYPE_U64, - PTYPE_S8, - PTYPE_S16, - PTYPE_S32, - PTYPE_S64, - PTYPE_EOL, - } type; + enum PrimitiveTypeKind type; const char *description; } PrimitiveType; +typedef struct PrimitiveList { + union { + strList *strings; + boolList *booleans; + numberList *numbers; + intList *integers; + int8List *s8_integers; + int16List *s16_integers; + int32List *s32_integers; + int64List *s64_integers; + uint8List *u8_integers; + uint16List *u16_integers; + uint32List *u32_integers; + uint64List *u64_integers; + } value; + enum PrimitiveTypeKind type; + const char *description; +} PrimitiveList; + /* test helpers */ +typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp); + +static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp) +{ + QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new(); + + visit(qapi_dealloc_get_visitor(qdv), &native_in, errp); + + qapi_dealloc_visitor_cleanup(qdv); +} + static void visit_primitive_type(Visitor *v, void **native, Error **errp) { PrimitiveType *pt = *native; @@ -105,6 +140,51 @@ static void visit_primitive_type(Visitor *v, void **native, Error **errp) } } +static void visit_primitive_list(Visitor *v, void **native, Error **errp) +{ + PrimitiveList *pl = *native; + switch (pl->type) { + case PTYPE_STRING: + visit_type_strList(v, &pl->value.strings, NULL, errp); + break; + case PTYPE_BOOLEAN: + visit_type_boolList(v, &pl->value.booleans, NULL, errp); + break; + case PTYPE_NUMBER: + visit_type_numberList(v, &pl->value.numbers, NULL, errp); + break; + case PTYPE_INTEGER: + visit_type_intList(v, &pl->value.integers, NULL, errp); + break; + case PTYPE_S8: + visit_type_int8List(v, &pl->value.s8_integers, NULL, errp); + break; + case PTYPE_S16: + visit_type_int16List(v, &pl->value.s16_integers, NULL, errp); + break; + case PTYPE_S32: + visit_type_int32List(v, &pl->value.s32_integers, NULL, errp); + break; + case PTYPE_S64: + visit_type_int64List(v, &pl->value.s64_integers, NULL, errp); + break; + case PTYPE_U8: + visit_type_uint8List(v, &pl->value.u8_integers, NULL, errp); + break; + case PTYPE_U16: + visit_type_uint16List(v, &pl->value.u16_integers, NULL, errp); + break; + case PTYPE_U32: + visit_type_uint32List(v, &pl->value.u32_integers, NULL, errp); + break; + case PTYPE_U64: + visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp); + break; + default: + g_assert(false); + } +} + typedef struct TestStruct { int64_t integer; @@ -206,12 +286,11 @@ static void visit_nested_struct_list(Visitor *v, void **native, Error **errp) /* test cases */ -typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp); - typedef enum VisitorCapabilities { VCAP_PRIMITIVES = 1, VCAP_STRUCTURES = 2, VCAP_LISTS = 4, + VCAP_PRIMITIVE_LISTS = 8, } VisitorCapabilities; typedef struct SerializeOps { @@ -229,17 +308,6 @@ typedef struct TestArgs { void *test_data; } TestArgs; -#define FLOAT_STRING_PRECISION 6 /* corresponding to n in %.nf formatting */ -static gsize calc_float_string_storage(double value) -{ - int whole_value = value; - gsize i = 0; - do { - i++; - } while (whole_value /= 10); - return i + 2 + FLOAT_STRING_PRECISION; -} - static void test_primitives(gconstpointer opaque) { TestArgs *args = (TestArgs *) opaque; @@ -248,7 +316,6 @@ static void test_primitives(gconstpointer opaque) PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy)); Error *err = NULL; void *serialize_data; - char *double1, *double2; pt_copy->type = pt->type; ops->serialize(pt, &serialize_data, visit_primitive_type, &err); @@ -260,14 +327,17 @@ static void test_primitives(gconstpointer opaque) g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string); g_free((char *)pt_copy->value.string); } else if (pt->type == PTYPE_NUMBER) { + GString *double_expected = g_string_new(""); + GString *double_actual = g_string_new(""); /* we serialize with %f for our reference visitors, so rather than fuzzy * floating math to test "equality", just compare the formatted values */ - double1 = g_malloc0(calc_float_string_storage(pt->value.number)); - double2 = g_malloc0(calc_float_string_storage(pt_copy->value.number)); - g_assert_cmpstr(double1, ==, double2); - g_free(double1); - g_free(double2); + g_string_printf(double_expected, "%.6f", pt->value.number); + g_string_printf(double_actual, "%.6f", pt_copy->value.number); + g_assert_cmpstr(double_actual->str, ==, double_expected->str); + + g_string_free(double_expected, true); + g_string_free(double_actual, true); } else if (pt->type == PTYPE_BOOLEAN) { g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max); } else { @@ -279,6 +349,328 @@ static void test_primitives(gconstpointer opaque) g_free(pt_copy); } +static void test_primitive_lists(gconstpointer opaque) +{ + TestArgs *args = (TestArgs *) opaque; + const SerializeOps *ops = args->ops; + PrimitiveType *pt = args->test_data; + PrimitiveList pl = { .value = { 0 } }; + PrimitiveList pl_copy = { .value = { 0 } }; + PrimitiveList *pl_copy_ptr = &pl_copy; + Error *err = NULL; + void *serialize_data; + void *cur_head = NULL; + int i; + + pl.type = pl_copy.type = pt->type; + + /* build up our list of primitive types */ + for (i = 0; i < 32; i++) { + switch (pl.type) { + case PTYPE_STRING: { + strList *tmp = g_new0(strList, 1); + tmp->value = g_strdup(pt->value.string); + if (pl.value.strings == NULL) { + pl.value.strings = tmp; + } else { + tmp->next = pl.value.strings; + pl.value.strings = tmp; + } + break; + } + case PTYPE_INTEGER: { + intList *tmp = g_new0(intList, 1); + tmp->value = pt->value.integer; + if (pl.value.integers == NULL) { + pl.value.integers = tmp; + } else { + tmp->next = pl.value.integers; + pl.value.integers = tmp; + } + break; + } + case PTYPE_S8: { + int8List *tmp = g_new0(int8List, 1); + tmp->value = pt->value.s8; + if (pl.value.s8_integers == NULL) { + pl.value.s8_integers = tmp; + } else { + tmp->next = pl.value.s8_integers; + pl.value.s8_integers = tmp; + } + break; + } + case PTYPE_S16: { + int16List *tmp = g_new0(int16List, 1); + tmp->value = pt->value.s16; + if (pl.value.s16_integers == NULL) { + pl.value.s16_integers = tmp; + } else { + tmp->next = pl.value.s16_integers; + pl.value.s16_integers = tmp; + } + break; + } + case PTYPE_S32: { + int32List *tmp = g_new0(int32List, 1); + tmp->value = pt->value.s32; + if (pl.value.s32_integers == NULL) { + pl.value.s32_integers = tmp; + } else { + tmp->next = pl.value.s32_integers; + pl.value.s32_integers = tmp; + } + break; + } + case PTYPE_S64: { + int64List *tmp = g_new0(int64List, 1); + tmp->value = pt->value.s64; + if (pl.value.s64_integers == NULL) { + pl.value.s64_integers = tmp; + } else { + tmp->next = pl.value.s64_integers; + pl.value.s64_integers = tmp; + } + break; + } + case PTYPE_U8: { + uint8List *tmp = g_new0(uint8List, 1); + tmp->value = pt->value.u8; + if (pl.value.u8_integers == NULL) { + pl.value.u8_integers = tmp; + } else { + tmp->next = pl.value.u8_integers; + pl.value.u8_integers = tmp; + } + break; + } + case PTYPE_U16: { + uint16List *tmp = g_new0(uint16List, 1); + tmp->value = pt->value.u16; + if (pl.value.u16_integers == NULL) { + pl.value.u16_integers = tmp; + } else { + tmp->next = pl.value.u16_integers; + pl.value.u16_integers = tmp; + } + break; + } + case PTYPE_U32: { + uint32List *tmp = g_new0(uint32List, 1); + tmp->value = pt->value.u32; + if (pl.value.u32_integers == NULL) { + pl.value.u32_integers = tmp; + } else { + tmp->next = pl.value.u32_integers; + pl.value.u32_integers = tmp; + } + break; + } + case PTYPE_U64: { + uint64List *tmp = g_new0(uint64List, 1); + tmp->value = pt->value.u64; + if (pl.value.u64_integers == NULL) { + pl.value.u64_integers = tmp; + } else { + tmp->next = pl.value.u64_integers; + pl.value.u64_integers = tmp; + } + break; + } + case PTYPE_NUMBER: { + numberList *tmp = g_new0(numberList, 1); + tmp->value = pt->value.number; + if (pl.value.numbers == NULL) { + pl.value.numbers = tmp; + } else { + tmp->next = pl.value.numbers; + pl.value.numbers = tmp; + } + break; + } + case PTYPE_BOOLEAN: { + boolList *tmp = g_new0(boolList, 1); + tmp->value = pt->value.boolean; + if (pl.value.booleans == NULL) { + pl.value.booleans = tmp; + } else { + tmp->next = pl.value.booleans; + pl.value.booleans = tmp; + } + break; + } + default: + g_assert(0); + } + } + + ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err); + ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err); + + g_assert(err == NULL); + i = 0; + + /* compare our deserialized list of primitives to the original */ + do { + switch (pl_copy.type) { + case PTYPE_STRING: { + strList *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.strings; + } + g_assert_cmpstr(pt->value.string, ==, ptr->value); + break; + } + case PTYPE_INTEGER: { + intList *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.integers; + } + g_assert_cmpint(pt->value.integer, ==, ptr->value); + break; + } + case PTYPE_S8: { + int8List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s8_integers; + } + g_assert_cmpint(pt->value.s8, ==, ptr->value); + break; + } + case PTYPE_S16: { + int16List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s16_integers; + } + g_assert_cmpint(pt->value.s16, ==, ptr->value); + break; + } + case PTYPE_S32: { + int32List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s32_integers; + } + g_assert_cmpint(pt->value.s32, ==, ptr->value); + break; + } + case PTYPE_S64: { + int64List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.s64_integers; + } + g_assert_cmpint(pt->value.s64, ==, ptr->value); + break; + } + case PTYPE_U8: { + uint8List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u8_integers; + } + g_assert_cmpint(pt->value.u8, ==, ptr->value); + break; + } + case PTYPE_U16: { + uint16List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u16_integers; + } + g_assert_cmpint(pt->value.u16, ==, ptr->value); + break; + } + case PTYPE_U32: { + uint32List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u32_integers; + } + g_assert_cmpint(pt->value.u32, ==, ptr->value); + break; + } + case PTYPE_U64: { + uint64List *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.u64_integers; + } + g_assert_cmpint(pt->value.u64, ==, ptr->value); + break; + } + case PTYPE_NUMBER: { + numberList *ptr; + GString *double_expected = g_string_new(""); + GString *double_actual = g_string_new(""); + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.numbers; + } + /* we serialize with %f for our reference visitors, so rather than + * fuzzy floating math to test "equality", just compare the + * formatted values + */ + g_string_printf(double_expected, "%.6f", pt->value.number); + g_string_printf(double_actual, "%.6f", ptr->value); + g_assert_cmpstr(double_actual->str, ==, double_expected->str); + g_string_free(double_expected, true); + g_string_free(double_actual, true); + break; + } + case PTYPE_BOOLEAN: { + boolList *ptr; + if (cur_head) { + ptr = cur_head; + cur_head = ptr->next; + } else { + cur_head = ptr = pl_copy.value.booleans; + } + g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value); + break; + } + default: + g_assert(0); + } + i++; + } while (cur_head); + + g_assert_cmpint(i, ==, 33); + + ops->cleanup(serialize_data); + dealloc_helper(&pl, visit_primitive_list, &err); + g_assert(!err); + dealloc_helper(&pl_copy, visit_primitive_list, &err); + g_assert(!err); + g_free(args); +} + static void test_struct(gconstpointer opaque) { TestArgs *args = (TestArgs *) opaque; @@ -728,7 +1120,8 @@ static const SerializeOps visitors[] = { .serialize = qmp_serialize, .deserialize = qmp_deserialize, .cleanup = qmp_cleanup, - .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS + .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS | + VCAP_PRIMITIVE_LISTS }, { .type = "String", @@ -782,6 +1175,19 @@ static void add_visitor_type(const SerializeOps *ops) args->test_data = NULL; g_test_add_data_func(testname, args, test_nested_struct_list); } + + if (ops->caps & VCAP_PRIMITIVE_LISTS) { + i = 0; + while (pt_values[i].type != PTYPE_EOL) { + sprintf(testname, "%s/primitive_list/%s", testname_prefix, + pt_values[i].description); + args = g_malloc0(sizeof(*args)); + args->ops = ops; + args->test_data = &pt_values[i]; + g_test_add_data_func(testname, args, test_primitive_lists); + i++; + } + } } int main(int argc, char **argv) diff --git a/trace-events b/trace-events index 9c73931f37..c5f1ccb96d 100644 --- a/trace-events +++ b/trace-events @@ -813,9 +813,6 @@ xen_map_cache_return(void* ptr) "%p" xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64 xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx" -# exec.c -qemu_put_ram_ptr(void* addr) "%p" - # hw/xen_platform.c xen_platform_log(char *s) "xen platform: %s" @@ -825,7 +822,7 @@ qemu_coroutine_yield(void *from, void *to) "from %p to %p" qemu_coroutine_terminate(void *co) "self %p" # qemu-coroutine-lock.c -qemu_co_queue_next_bh(void) "" +qemu_co_queue_run_restart(void *co) "co %p" qemu_co_queue_next(void *nxt) "next %p" qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p" qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p" diff --git a/translate-all.c b/translate-all.c index da93608f03..211be314cb 100644 --- a/translate-all.c +++ b/translate-all.c @@ -55,7 +55,6 @@ #else #include "exec/address-spaces.h" #endif -#include "qemu/timer.h" #include "exec/cputlb.h" #include "translate-all.h" @@ -1359,7 +1358,7 @@ void tb_invalidate_phys_addr(hwaddr addr) section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS); if (!(memory_region_is_ram(section->mr) - || (section->mr->rom_device && section->mr->readable))) { + || memory_region_is_romd(section->mr))) { return; } ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK) diff --git a/ui/cocoa.m b/ui/cocoa.m index 1971d9cb09..be491794dc 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -35,6 +35,9 @@ #ifndef MAC_OS_X_VERSION_10_5 #define MAC_OS_X_VERSION_10_5 1050 #endif +#ifndef MAC_OS_X_VERSION_10_6 +#define MAC_OS_X_VERSION_10_6 1060 +#endif //#define DEBUG @@ -771,9 +774,20 @@ QemuCocoaView *cocoaView; NSOpenPanel *op = [[NSOpenPanel alloc] init]; [op setPrompt:@"Boot image"]; [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; - [op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil] + NSArray *filetypes = [NSArray arrayWithObjects:@"img", @"iso", @"dmg", + @"qcow", @"cow", @"cloop", @"vmdk", nil]; +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) + [op setAllowedFileTypes:filetypes]; + [op beginSheetModalForWindow:normalWindow + completionHandler:^(NSInteger returnCode) + { [self openPanelDidEnd:op + returnCode:returnCode contextInfo:NULL ]; } ]; +#else + // Compatibility code for pre-10.6, using deprecated method + [op beginSheetForDirectory:nil file:nil types:filetypes modalForWindow:normalWindow modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; +#endif } else { // or launch QEMU, with the global args [self startEmulationWithArgc:gArgc argv:(char **)gArgv]; @@ -810,7 +824,7 @@ QemuCocoaView *cocoaView; exit(0); } else if(returnCode == NSOKButton) { const char *bin = "qemu"; - char *img = (char*)[ [ sheet filename ] cStringUsingEncoding:NSASCIIStringEncoding]; + char *img = (char*)[ [ [ sheet URL ] path ] cStringUsingEncoding:NSASCIIStringEncoding]; char **argv = (char**)malloc( sizeof(char*)*3 ); @@ -851,22 +865,10 @@ QemuCocoaView *cocoaView; -// Dock Connection -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - int main (int argc, const char * argv[]) { gArgc = argc; gArgv = (char **)argv; - CPSProcessSerNum PSN; int i; /* In case we don't need to display a window, let's not do that */ @@ -890,12 +892,13 @@ int main (int argc, const char * argv[]) { } NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - [NSApplication sharedApplication]; - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [NSApplication sharedApplication]; + // Pull this console process up to being a fully-fledged graphical + // app with a menubar and Dock icon + ProcessSerialNumber psn = { 0, kCurrentProcess }; + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + + [NSApplication sharedApplication]; // Add menus NSMenu *menu; @@ -960,6 +963,8 @@ int main (int argc, const char * argv[]) { static void cocoa_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); NSRect rect; @@ -973,18 +978,24 @@ static void cocoa_update(DisplayChangeListener *dcl, h * [cocoaView cdy]); } [cocoaView setNeedsDisplayInRect:rect]; + + [pool release]; } static void cocoa_switch(DisplayChangeListener *dcl, DisplaySurface *surface) { - COCOA_DEBUG("qemu_cocoa: cocoa_resize\n"); + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + COCOA_DEBUG("qemu_cocoa: cocoa_switch\n"); [cocoaView switchSurface:surface]; + [pool release]; } static void cocoa_refresh(DisplayChangeListener *dcl) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); if (kbd_mouse_is_absolute()) { @@ -1007,6 +1018,7 @@ static void cocoa_refresh(DisplayChangeListener *dcl) } } while(event != nil); graphic_hw_update(NULL); + [pool release]; } static void cocoa_cleanup(void) diff --git a/ui/input.c b/ui/input.c index 8ca1a03e12..92c44ca810 100644 --- a/ui/input.c +++ b/ui/input.c @@ -28,6 +28,7 @@ #include "qapi/error.h" #include "qmp-commands.h" #include "qapi-types.h" +#include "ui/keymaps.h" struct QEMUPutMouseEntry { QEMUPutMouseEvent *qemu_put_mouse_event; @@ -260,10 +261,10 @@ static void free_keycodes(void) static void release_keys(void *opaque) { while (keycodes_size > 0) { - if (keycodes[--keycodes_size] & 0x80) { - kbd_put_keycode(0xe0); + if (keycodes[--keycodes_size] & SCANCODE_GREY) { + kbd_put_keycode(SCANCODE_EMUL0); } - kbd_put_keycode(keycodes[keycodes_size] | 0x80); + kbd_put_keycode(keycodes[keycodes_size] | SCANCODE_UP); } free_keycodes(); @@ -297,10 +298,10 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, return; } - if (keycode & 0x80) { - kbd_put_keycode(0xe0); + if (keycode & SCANCODE_GREY) { + kbd_put_keycode(SCANCODE_EMUL0); } - kbd_put_keycode(keycode & 0x7f); + kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK); keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1)); keycodes[keycodes_size++] = keycode; @@ -3366,8 +3366,10 @@ int main(int argc, char **argv, char **envp) break; } case QEMU_OPTION_monitor: - monitor_parse(optarg, "readline"); default_monitor = 0; + if (strncmp(optarg, "none", 4)) { + monitor_parse(optarg, "readline"); + } break; case QEMU_OPTION_qmp: monitor_parse(optarg, "control"); |