diff options
36 files changed, 337 insertions, 265 deletions
@@ -293,7 +293,7 @@ ifdef INSTALL_BLOBS BLOBS=bios.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \ vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \ acpi-dsdt.aml q35-acpi-dsdt.aml \ -ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \ +ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin \ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \ pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \ efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \ @@ -1 +1 @@ -1.6.90 +1.6.91 diff --git a/backends/rng-egd.c b/backends/rng-egd.c index 9e5a5366f7..25bb3b453b 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -91,12 +91,14 @@ static int rng_egd_chr_can_read(void *opaque) static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size) { RngEgd *s = RNG_EGD(opaque); + size_t buf_offset = 0; while (size > 0 && s->requests) { RngRequest *req = s->requests->data; int len = MIN(size, req->size - req->offset); - memcpy(req->data + req->offset, buf, len); + memcpy(req->data + req->offset, buf + buf_offset, len); + buf_offset += len; req->offset += len; size -= len; @@ -167,7 +169,6 @@ static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp) if (b->opened) { error_set(errp, QERR_PERMISSION_DENIED); } else { - g_free(s->chr_name); s->chr_name = g_strdup(value); } } @@ -323,6 +323,9 @@ query_pkg_config() { pkg_config=query_pkg_config sdl_config="${SDL_CONFIG-${cross_prefix}sdl-config}" +# If the user hasn't specified ARFLAGS, default to 'rv', just as make does. +ARFLAGS="${ARFLAGS-rv}" + # default flags for all hosts QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS" QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" @@ -3695,6 +3698,7 @@ echo "C compiler $cc" echo "Host C compiler $host_cc" echo "C++ compiler $cxx" echo "Objective-C compiler $objcc" +echo "ARFLAGS $ARFLAGS" echo "CFLAGS $CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" echo "LDFLAGS $LDFLAGS" @@ -4276,6 +4280,7 @@ echo "HOST_CC=$host_cc" >> $config_host_mak echo "CXX=$cxx" >> $config_host_mak echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak +echo "ARFLAGS=$ARFLAGS" >> $config_host_mak echo "AS=$as" >> $config_host_mak echo "CPP=$cpp" >> $config_host_mak echo "OBJCOPY=$objcopy" >> $config_host_mak diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 0eada32dcf..729efa81a2 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -205,6 +205,11 @@ static int parse_netdev(DeviceState *dev, const char *str, void **ptr) goto err; } + if (ncs[i]) { + ret = -EINVAL; + goto err; + } + ncs[i] = peers[i]; ncs[i]->queue_index = i; } @@ -301,6 +306,10 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, *ptr = NULL; return; } + if (*ptr) { + error_set_from_qdev_prop_error(errp, -EINVAL, dev, prop, name); + return; + } hubport = net_hub_port_find(id); if (!hubport) { diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 24876d33ef..873b82c8db 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -25,8 +25,12 @@ #include "qemu-common.h" #include "ui/console.h" #include "ui/pixel_ops.h" +#include "hw/loader.h" #include "hw/sysbus.h" +#define TCX_ROM_FILE "QEMU,tcx.bin" +#define FCODE_MAX_ROM_SIZE 0x10000 + #define MAXX 1024 #define MAXY 768 #define TCX_DAC_NREGS 16 @@ -43,6 +47,8 @@ typedef struct TCXState { QemuConsole *con; uint8_t *vram; uint32_t *vram24, *cplane; + hwaddr prom_addr; + MemoryRegion rom; MemoryRegion vram_mem; MemoryRegion vram_8bit; MemoryRegion vram_24bit; @@ -529,14 +535,31 @@ static int tcx_init1(SysBusDevice *dev) { TCXState *s = TCX(dev); ram_addr_t vram_offset = 0; - int size; + int size, ret; uint8_t *vram_base; + char *fcode_filename; memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram", s->vram_size * (1 + 4 + 4)); vmstate_register_ram_global(&s->vram_mem); vram_base = memory_region_get_ram_ptr(&s->vram_mem); + /* FCode ROM */ + memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE); + vmstate_register_ram_global(&s->rom); + memory_region_set_readonly(&s->rom, true); + sysbus_init_mmio(dev, &s->rom); + + fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, TCX_ROM_FILE); + if (fcode_filename) { + ret = load_image_targphys(fcode_filename, s->prom_addr, + FCODE_MAX_ROM_SIZE); + if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) { + fprintf(stderr, "tcx: could not load prom '%s'\n", TCX_ROM_FILE); + return -1; + } + } + /* 8-bit plane */ s->vram = vram_base; size = s->vram_size; @@ -598,6 +621,7 @@ static Property tcx_properties[] = { DEFINE_PROP_UINT16("width", TCXState, width, -1), DEFINE_PROP_UINT16("height", TCXState, height, -1), DEFINE_PROP_UINT16("depth", TCXState, depth, -1), + DEFINE_PROP_HEX64("prom_addr", TCXState, prom_addr, -1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index aae43097aa..968680104b 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -154,55 +154,19 @@ static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region, uint64_t val = 0; int fd = dev_region->region->resource_fd; - if (fd >= 0) { - if (data) { - DEBUG("pwrite data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx - ", addr="TARGET_FMT_plx"\n", *data, size, addr, addr); - if (pwrite(fd, data, size, addr) != size) { - error_report("%s - pwrite failed %s", - __func__, strerror(errno)); - } - } else { - if (pread(fd, &val, size, addr) != size) { - error_report("%s - pread failed %s", - __func__, strerror(errno)); - val = (1UL << (size * 8)) - 1; - } - DEBUG("pread val=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx - ", addr=" TARGET_FMT_plx "\n", val, size, addr, addr); + if (data) { + DEBUG("pwrite data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx + ", addr="TARGET_FMT_plx"\n", *data, size, addr, addr); + if (pwrite(fd, data, size, addr) != size) { + error_report("%s - pwrite failed %s", __func__, strerror(errno)); } } else { - uint32_t port = addr + dev_region->u.r_baseport; - - if (data) { - DEBUG("out data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx - ", host=%x\n", *data, size, addr, port); - switch (size) { - case 1: - outb(*data, port); - break; - case 2: - outw(*data, port); - break; - case 4: - outl(*data, port); - break; - } - } else { - switch (size) { - case 1: - val = inb(port); - break; - case 2: - val = inw(port); - break; - case 4: - val = inl(port); - break; - } - DEBUG("in data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx - ", host=%x\n", val, size, addr, port); + if (pread(fd, &val, size, addr) != size) { + error_report("%s - pread failed %s", __func__, strerror(errno)); + val = (1UL << (size * 8)) - 1; } + DEBUG("pread val=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx + ", addr=" TARGET_FMT_plx "\n", val, size, addr, addr); } return val; } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 094c4212e6..2111f0192c 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -57,7 +57,6 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; -static bool has_pvpanic; static bool has_pci_info; static bool has_acpi_build = true; @@ -229,10 +228,6 @@ static void pc_init1(QEMUMachineInitArgs *args, if (pci_enabled) { pc_pci_device_init(pci_bus); } - - if (has_pvpanic) { - pvpanic_init(isa_bus); - } } static void pc_init_pci(QEMUMachineInitArgs *args) @@ -250,13 +245,11 @@ static void pc_compat_1_6(QEMUMachineInitArgs *args) static void pc_compat_1_5(QEMUMachineInitArgs *args) { pc_compat_1_6(args); - has_pvpanic = true; } static void pc_compat_1_4(QEMUMachineInitArgs *args) { pc_compat_1_5(args); - has_pvpanic = false; x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 1af8e2b943..600fc02ebe 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -47,7 +47,6 @@ /* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6 -static bool has_pvpanic; static bool has_pci_info; static bool has_acpi_build = true; @@ -216,10 +215,6 @@ static void pc_q35_init(QEMUMachineInitArgs *args) if (pci_enabled) { pc_pci_device_init(host_bus); } - - if (has_pvpanic) { - pvpanic_init(isa_bus); - } } static void pc_compat_1_6(QEMUMachineInitArgs *args) @@ -232,13 +227,11 @@ static void pc_compat_1_6(QEMUMachineInitArgs *args) static void pc_compat_1_5(QEMUMachineInitArgs *args) { pc_compat_1_6(args); - has_pvpanic = true; } static void pc_compat_1_4(QEMUMachineInitArgs *args) { pc_compat_1_5(args); - has_pvpanic = false; x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); } diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 49bdd024ed..5f6dd9f588 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -108,6 +108,18 @@ static void cpu_request_exit(void *opaque, int irq, int level) } } +static CPUUnassignedAccess real_do_unassigned_access; +static void mips_jazz_do_unassigned_access(CPUState *cpu, hwaddr addr, + bool is_write, bool is_exec, + int opaque, unsigned size) +{ + if (!is_exec) { + /* ignore invalid access (ie do not raise exception) */ + return; + } + (*real_do_unassigned_access)(cpu, addr, is_write, is_exec, opaque, size); +} + static void mips_jazz_init(MemoryRegion *address_space, MemoryRegion *address_space_io, ram_addr_t ram_size, @@ -117,6 +129,7 @@ static void mips_jazz_init(MemoryRegion *address_space, char *filename; int bios_size, n; MIPSCPU *cpu; + CPUClass *cc; CPUMIPSState *env; qemu_irq *rc4030, *i8259; rc4030_dma *dmas; @@ -154,6 +167,17 @@ static void mips_jazz_init(MemoryRegion *address_space, env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); + /* Chipset returns 0 in invalid reads and do not raise data exceptions. + * However, we can't simply add a global memory region to catch + * everything, as memory core directly call unassigned_mem_read/write + * on some invalid accesses, which call do_unassigned_access on the + * CPU, which raise an exception. + * Handle that case by hijacking the do_unassigned_access method on + * the CPU, and do not raise exceptions for data access. */ + cc = CPU_GET_CLASS(cpu); + real_do_unassigned_access = cc->do_unassigned_access; + cc->do_unassigned_access = mips_jazz_do_unassigned_access; + /* allocate RAM */ memory_region_init_ram(ram, NULL, "mips_jazz.ram", ram_size); vmstate_register_ram_global(ram); diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index 226e2983d3..5377feed69 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -112,11 +112,6 @@ static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(d, &s->io, s->ioport); } -void pvpanic_init(ISABus *bus) -{ - isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE); -} - #define PVPANIC_IOPORT_PROP "ioport" uint16_t pvpanic_port(void) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index fe95e03d1d..f7f8a19ee8 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -3568,6 +3568,13 @@ static int vfio_initfn(PCIDevice *pdev) vdev->emulated_config_bits[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_MULTI_FUNCTION; + /* Restore or clear multifunction, this is always controlled by QEMU */ + if (vdev->pdev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { + vdev->pdev.config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION; + } else { + vdev->pdev.config[PCI_HEADER_TYPE] &= ~PCI_HEADER_TYPE_MULTI_FUNCTION; + } + /* * Clear host resource mapping info. If we choose not to register a * BAR, such as might be the case with the option ROM, we can get diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c index 988ca20898..9c54945107 100644 --- a/hw/openrisc/cputimer.c +++ b/hw/openrisc/cputimer.c @@ -30,19 +30,28 @@ static int is_counting; void cpu_openrisc_count_update(OpenRISCCPU *cpu) { - uint64_t now, next; - uint32_t wait; + uint64_t now; - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if (!is_counting) { - timer_del(cpu->env.timer); - last_clk = now; return; } - + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ, get_ticks_per_sec()); last_clk = now; +} + +void cpu_openrisc_timer_update(OpenRISCCPU *cpu) +{ + uint32_t wait; + uint64_t now, next; + + if (!is_counting) { + return; + } + + cpu_openrisc_count_update(cpu); + now = last_clk; if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) { wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1; @@ -50,7 +59,6 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu) } else { wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP); } - next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ); timer_mod(cpu->env.timer, next); } @@ -63,8 +71,9 @@ void cpu_openrisc_count_start(OpenRISCCPU *cpu) void cpu_openrisc_count_stop(OpenRISCCPU *cpu) { - is_counting = 0; + timer_del(cpu->env.timer); cpu_openrisc_count_update(cpu); + is_counting = 0; } static void openrisc_timer_cb(void *opaque) @@ -84,15 +93,15 @@ static void openrisc_timer_cb(void *opaque) break; case TIMER_INTR: cpu->env.ttcr = 0; - cpu_openrisc_count_start(cpu); break; case TIMER_SHOT: cpu_openrisc_count_stop(cpu); break; case TIMER_CONT: - cpu_openrisc_count_start(cpu); break; } + + cpu_openrisc_timer_update(cpu); } void cpu_openrisc_clock_init(OpenRISCCPU *cpu) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index a0d366cbbc..94f79508d8 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -537,24 +537,27 @@ static void tcx_init(hwaddr addr, int vram_size, int width, qdev_prop_set_uint16(dev, "width", width); qdev_prop_set_uint16(dev, "height", height); qdev_prop_set_uint16(dev, "depth", depth); + qdev_prop_set_uint64(dev, "prom_addr", addr); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); + /* FCode ROM */ + sysbus_mmio_map(s, 0, addr); /* 8-bit plane */ - sysbus_mmio_map(s, 0, addr + 0x00800000ULL); + sysbus_mmio_map(s, 1, addr + 0x00800000ULL); /* DAC */ - sysbus_mmio_map(s, 1, addr + 0x00200000ULL); + sysbus_mmio_map(s, 2, addr + 0x00200000ULL); /* TEC (dummy) */ - sysbus_mmio_map(s, 2, addr + 0x00700000ULL); + sysbus_mmio_map(s, 3, addr + 0x00700000ULL); /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */ - sysbus_mmio_map(s, 3, addr + 0x00301000ULL); + sysbus_mmio_map(s, 4, addr + 0x00301000ULL); if (depth == 24) { /* 24-bit plane */ - sysbus_mmio_map(s, 4, addr + 0x02000000ULL); + sysbus_mmio_map(s, 5, addr + 0x02000000ULL); /* Control plane */ - sysbus_mmio_map(s, 5, addr + 0x0a000000ULL); + sysbus_mmio_map(s, 6, addr + 0x0a000000ULL); } else { /* THC 8 bit (dummy) */ - sysbus_mmio_map(s, 4, addr + 0x00300000ULL); + sysbus_mmio_map(s, 5, addr + 0x00300000ULL); } } diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index 314e393520..b22ccf1008 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -139,6 +139,12 @@ static int virtio_rng_device_init(VirtIODevice *vdev) VirtIORNG *vrng = VIRTIO_RNG(vdev); Error *local_err = NULL; + if (!vrng->conf.period_ms > 0) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, "period", + "a positive number"); + return -1; + } + if (vrng->conf.rng == NULL) { vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM)); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 57e8d16180..09652fb22c 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -235,7 +235,6 @@ void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw); /* pvpanic.c */ -void pvpanic_init(ISABus *bus); uint16_t pvpanic_port(void); /* e820 types */ diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index 0aa8913301..492bce1c1b 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -168,14 +168,14 @@ #endif #ifndef atomic_xchg -#ifdef __ATOMIC_SEQ_CST +#if defined(__clang__) +#define atomic_xchg(ptr, i) __sync_swap(ptr, i) +#elif defined(__ATOMIC_SEQ_CST) #define atomic_xchg(ptr, i) ({ \ typeof(*ptr) _new = (i), _old; \ __atomic_exchange(ptr, &_new, &_old, __ATOMIC_SEQ_CST); \ _old; \ }) -#elif defined __clang__ -#define atomic_xchg(ptr, i) __sync_exchange(ptr, i) #else /* __sync_lock_test_and_set() is documented to be an acquire barrier only. */ #define atomic_xchg(ptr, i) (smp_mb(), __sync_lock_test_and_set(ptr, i)) diff --git a/pc-bios/QEMU,tcx.bin b/pc-bios/QEMU,tcx.bin Binary files differnew file mode 100644 index 0000000000..a8ddd70ef3 --- /dev/null +++ b/pc-bios/QEMU,tcx.bin diff --git a/pc-bios/README b/pc-bios/README index 1501cf14b4..a110125a97 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -11,8 +11,8 @@ firmware implementation. The goal is to implement a 100% IEEE 1275-1994 (referred to as Open Firmware) compliant firmware. The included images for PowerPC (for 32 and 64 bit PPC CPUs), - Sparc32 and Sparc64 are built from OpenBIOS SVN revision - 1229. + Sparc32 (including QEMU,tcx.bin) and Sparc64 are built from OpenBIOS SVN + revision 1229. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 10682f58dc..8100bee67e 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -401,7 +401,7 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E return -1; } - slog("guest-file-open, handle: %d", handle); + slog("guest-file-open, handle: %" PRId64, handle); return handle; } @@ -410,7 +410,7 @@ void qmp_guest_file_close(int64_t handle, Error **err) GuestFileHandle *gfh = guest_file_handle_find(handle, err); int ret; - slog("guest-file-close called, handle: %ld", handle); + slog("guest-file-close called, handle: %" PRId64, handle); if (!gfh) { return; } @@ -451,7 +451,7 @@ struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, read_count = fread(buf, 1, count, fh); if (ferror(fh)) { error_setg_errno(err, errno, "failed to read file"); - slog("guest-file-read failed, handle: %ld", handle); + slog("guest-file-read failed, handle: %" PRId64, handle); } else { buf[read_count] = 0; read_data = g_malloc0(sizeof(GuestFileRead)); @@ -496,7 +496,7 @@ GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, write_count = fwrite(buf, 1, count, fh); if (ferror(fh)) { error_setg_errno(err, errno, "failed to write to file"); - slog("guest-file-write failed, handle: %ld", handle); + slog("guest-file-write failed, handle: %" PRId64, handle); } else { write_data = g_malloc0(sizeof(GuestFileWrite)); write_data->count = write_count; diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h index 624a559d94..e422208b4e 100644 --- a/qga/guest-agent-core.h +++ b/qga/guest-agent-core.h @@ -29,7 +29,7 @@ GACommandState *ga_command_state_new(void); bool ga_logging_enabled(GAState *s); void ga_disable_logging(GAState *s); void ga_enable_logging(GAState *s); -void slog(const gchar *fmt, ...); +void GCC_FMT_ATTR(1, 2) slog(const gchar *fmt, ...); void ga_set_response_delimited(GAState *s); bool ga_is_frozen(GAState *s); void ga_set_frozen(GAState *s); diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp index 37731a7271..b791a6c33b 100644 --- a/qga/vss-win32/install.cpp +++ b/qga/vss-win32/install.cpp @@ -25,8 +25,8 @@ extern HINSTANCE g_hinstDll; const GUID CLSID_COMAdminCatalog = { 0xF618C514, 0xDFB8, 0x11d1, {0xA2, 0xCF, 0x00, 0x80, 0x5F, 0xC7, 0x92, 0x35} }; -const GUID IID_ICOMAdminCatalog = { 0xDD662187, 0xDFC2, 0x11d1, - {0xA2, 0xCF, 0x00, 0x80, 0x5F, 0xC7, 0x92, 0x35} }; +const GUID IID_ICOMAdminCatalog2 = { 0x790C6E0B, 0x9194, 0x4cc9, + {0x94, 0x26, 0xA4, 0x8A, 0x63, 0x18, 0x56, 0x96} }; const GUID CLSID_WbemLocator = { 0x4590f811, 0x1d3a, 0x11d0, {0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24} }; const GUID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf, @@ -141,7 +141,7 @@ static HRESULT QGAProviderFind( HRESULT hr; COMInitializer initializer; COMPointer<IUnknown> pUnknown; - COMPointer<ICOMAdminCatalog> pCatalog; + COMPointer<ICOMAdminCatalog2> pCatalog; COMPointer<ICatalogCollection> pColl; COMPointer<ICatalogObject> pObj; _variant_t var; @@ -149,7 +149,7 @@ static HRESULT QGAProviderFind( chk(CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)pUnknown.replace())); - chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog, + chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog2, (void **)pCatalog.replace())); chk(pCatalog->GetCollection(_bstr_t(L"Applications"), (IDispatch **)pColl.replace())); @@ -206,7 +206,7 @@ STDAPI COMRegister(void) HRESULT hr; COMInitializer initializer; COMPointer<IUnknown> pUnknown; - COMPointer<ICOMAdminCatalog> pCatalog; + COMPointer<ICOMAdminCatalog2> pCatalog; COMPointer<ICatalogCollection> pApps, pRoles, pUsersInRole; COMPointer<ICatalogObject> pObj; long n; @@ -229,7 +229,7 @@ STDAPI COMRegister(void) chk(CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)pUnknown.replace())); - chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog, + chk(pUnknown->QueryInterface(IID_ICOMAdminCatalog2, (void **)pCatalog.replace())); /* Install COM+ Component */ @@ -273,6 +273,10 @@ STDAPI COMRegister(void) goto out; } + chk(pCatalog->CreateServiceForApplication( + _bstr_t(QGA_PROVIDER_LNAME), _bstr_t(QGA_PROVIDER_LNAME), + _bstr_t(L"SERVICE_AUTO_START"), _bstr_t(L"SERVICE_ERROR_NORMAL"), + _bstr_t(L""), _bstr_t(L".\\localsystem"), _bstr_t(L""), FALSE)); chk(pCatalog->InstallComponent(_bstr_t(QGA_PROVIDER_LNAME), _bstr_t(dllPath), _bstr_t(tlbPath), _bstr_t(""))); @@ -794,7 +794,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) if (l > size) l = size; memcpy(f->buf + f->buf_index, buf, l); - f->bytes_xfer += size; + f->bytes_xfer += l; if (f->ops->writev_buffer) { add_to_iovec(f, f->buf + f->buf_index, l); } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 864c80eb47..47af9a8816 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2086,14 +2086,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, /* cache info: needed for Core compatibility */ if (cpu->cache_info_passthrough) { host_cpuid(index, count, eax, ebx, ecx, edx); - break; - } - if (cs->nr_cores > 1) { - *eax = (cs->nr_cores - 1) << 26; + *eax &= ~0xFC000000; } else { *eax = 0; - } - switch (count) { + switch (count) { case 0: /* L1 dcache info */ *eax |= CPUID_4_TYPE_DCACHE | \ CPUID_4_LEVEL(1) | \ @@ -2133,6 +2129,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx = 0; *edx = 0; break; + } + } + + /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */ + if ((*eax & 31) && cs->nr_cores > 1) { + *eax |= (cs->nr_cores - 1) << 26; } break; case 5: diff --git a/target-i386/helper.h b/target-i386/helper.h index d6974dfd6b..3775abeba7 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -58,6 +58,7 @@ DEF_HELPER_2(sysret, void, env, int) DEF_HELPER_2(hlt, void, env, int) DEF_HELPER_2(monitor, void, env, tl) DEF_HELPER_2(mwait, void, env, int) +DEF_HELPER_2(pause, void, env, int) DEF_HELPER_1(debug, void, env) DEF_HELPER_1(reset_rf, void, env) DEF_HELPER_3(raise_interrupt, void, env, int, int) diff --git a/target-i386/kvm-stub.c b/target-i386/kvm-stub.c index 11429c461e..2b9e8011fb 100644 --- a/target-i386/kvm-stub.c +++ b/target-i386/kvm-stub.c @@ -16,3 +16,15 @@ bool kvm_allows_irq0_override(void) { return 1; } + +#ifndef __OPTIMIZE__ +/* This function is only called inside conditionals which we + * rely on the compiler to optimize out when CONFIG_KVM is not + * defined. + */ +uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, + uint32_t index, int reg) +{ + abort(); +} +#endif diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 749aa09a21..1188482359 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -456,11 +456,12 @@ int kvm_arch_init_vcpu(CPUState *cs) uint32_t signature[3]; int r; + memset(&cpuid_data, 0, sizeof(cpuid_data)); + cpuid_i = 0; /* Paravirtualization CPUIDs */ c = &cpuid_data.entries[cpuid_i++]; - memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_SIGNATURE; if (!hyperv_enabled(cpu)) { memcpy(signature, "KVMKVMKVM\0\0\0", 12); @@ -474,7 +475,6 @@ int kvm_arch_init_vcpu(CPUState *cs) c->edx = signature[2]; c = &cpuid_data.entries[cpuid_i++]; - memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_FEATURES; c->eax = env->features[FEAT_KVM]; @@ -483,13 +483,11 @@ int kvm_arch_init_vcpu(CPUState *cs) c->eax = signature[0]; c = &cpuid_data.entries[cpuid_i++]; - memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_VERSION; c->eax = 0x00001bbc; c->ebx = 0x00060001; c = &cpuid_data.entries[cpuid_i++]; - memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_FEATURES; if (cpu->hyperv_relaxed_timing) { c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; @@ -500,7 +498,6 @@ int kvm_arch_init_vcpu(CPUState *cs) } c = &cpuid_data.entries[cpuid_i++]; - memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_ENLIGHTMENT_INFO; if (cpu->hyperv_relaxed_timing) { c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED; @@ -511,13 +508,11 @@ int kvm_arch_init_vcpu(CPUState *cs) c->ebx = cpu->hyperv_spinlock_attempts; c = &cpuid_data.entries[cpuid_i++]; - memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_IMPLEMENT_LIMITS; c->eax = 0x40; c->ebx = 0x40; c = &cpuid_data.entries[cpuid_i++]; - memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_SIGNATURE_NEXT; memcpy(signature, "KVMKVMKVM\0\0\0", 12); c->eax = 0; @@ -1314,8 +1309,8 @@ static int kvm_get_xcrs(X86CPU *cpu) for (i = 0; i < xcrs.nr_xcrs; i++) { /* Only support xcr0 now */ - if (xcrs.xcrs[0].xcr == 0) { - env->xcr0 = xcrs.xcrs[0].value; + if (xcrs.xcrs[i].xcr == 0) { + env->xcr0 = xcrs.xcrs[i].value; break; } } diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c index 93933fd162..b6307ca386 100644 --- a/target-i386/misc_helper.c +++ b/target-i386/misc_helper.c @@ -566,6 +566,15 @@ void helper_rdmsr(CPUX86State *env) } #endif +static void do_pause(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + + /* Just let another CPU run. */ + env->exception_index = EXCP_INTERRUPT; + cpu_loop_exit(env); +} + static void do_hlt(X86CPU *cpu) { CPUState *cs = CPU(cpu); @@ -611,13 +620,22 @@ void helper_mwait(CPUX86State *env, int next_eip_addend) cs = CPU(cpu); /* XXX: not complete but not completely erroneous */ if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) { - /* more than one CPU: do not sleep because another CPU may - wake this one */ + do_pause(cpu); } else { do_hlt(cpu); } } +void helper_pause(CPUX86State *env, int next_eip_addend) +{ + X86CPU *cpu = x86_env_get_cpu(env); + + cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0); + env->eip += next_eip_addend; + + do_pause(cpu); +} + void helper_debug(CPUX86State *env) { env->exception_index = EXCP_DEBUG; diff --git a/target-i386/translate.c b/target-i386/translate.c index eb0ea93dbb..7916e5b1f6 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2090,6 +2090,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm, int scale; int opreg; int mod, rm, code, override, must_add_seg; + TCGv sum; override = s->override; must_add_seg = s->addseg; @@ -2099,10 +2100,9 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm, rm = modrm & 7; if (s->aflag) { - havesib = 0; base = rm; - index = 0; + index = -1; scale = 0; if (base == 4) { @@ -2110,6 +2110,9 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm, code = cpu_ldub_code(env, s->pc++); scale = (code >> 6) & 3; index = ((code >> 3) & 7) | REX_X(s); + if (index == 4) { + index = -1; /* no index */ + } base = (code & 7); } base |= REX_B(s); @@ -2137,59 +2140,57 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm, break; } - if (base >= 0) { - /* for correct popl handling with esp */ - if (base == 4 && s->popl_esp_hack) - disp += s->popl_esp_hack; -#ifdef TARGET_X86_64 - if (s->aflag == 2) { - gen_op_movq_A0_reg(base); - if (disp != 0) { - gen_op_addq_A0_im(disp); - } - } else -#endif - { - gen_op_movl_A0_reg(base); - if (disp != 0) - gen_op_addl_A0_im(disp); + /* For correct popl handling with esp. */ + if (base == R_ESP && s->popl_esp_hack) { + disp += s->popl_esp_hack; + } + + /* Compute the address, with a minimum number of TCG ops. */ + TCGV_UNUSED(sum); + if (index >= 0) { + if (scale == 0) { + sum = cpu_regs[index]; + } else { + tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale); + sum = cpu_A0; } - } else { -#ifdef TARGET_X86_64 - if (s->aflag == 2) { - gen_op_movq_A0_im(disp); - } else -#endif - { - gen_op_movl_A0_im(disp); + if (base >= 0) { + tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]); + sum = cpu_A0; } + } else if (base >= 0) { + sum = cpu_regs[base]; } - /* index == 4 means no index */ - if (havesib && (index != 4)) { -#ifdef TARGET_X86_64 - if (s->aflag == 2) { - gen_op_addq_A0_reg_sN(scale, index); - } else -#endif - { - gen_op_addl_A0_reg_sN(scale, index); - } + if (TCGV_IS_UNUSED(sum)) { + tcg_gen_movi_tl(cpu_A0, disp); + } else { + tcg_gen_addi_tl(cpu_A0, sum, disp); } + if (must_add_seg) { if (override < 0) { - if (base == R_EBP || base == R_ESP) + if (base == R_EBP || base == R_ESP) { override = R_SS; - else + } else { override = R_DS; + } } -#ifdef TARGET_X86_64 - if (s->aflag == 2) { - gen_op_addq_A0_seg(override); - } else -#endif - { - gen_op_addl_A0_seg(s, override); + + tcg_gen_ld_tl(cpu_tmp0, cpu_env, + offsetof(CPUX86State, segs[override].base)); + if (CODE64(s)) { + if (s->aflag != 2) { + tcg_gen_ext32u_tl(cpu_A0, cpu_A0); + } + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); + goto done; } + + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); + } + + if (s->aflag != 2) { + tcg_gen_ext32u_tl(cpu_A0, cpu_A0); } } else { switch (mod) { @@ -2259,6 +2260,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm, } } + done: opreg = OR_A0; disp = 0; *reg_ptr = opreg; @@ -7224,7 +7226,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, goto do_xchg_reg_eax; } if (prefixes & PREFIX_REPZ) { - gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE); + gen_update_cc_op(s); + gen_jmp_im(pc_start - s->cs_base); + gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start)); + s->is_jmp = DISAS_TB_JUMP; } break; case 0x9b: /* fwait */ diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 8fd0bc0bf0..0f9efdf6de 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -373,6 +373,7 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu); /* hw/openrisc_timer.c */ void cpu_openrisc_clock_init(OpenRISCCPU *cpu); void cpu_openrisc_count_update(OpenRISCCPU *cpu); +void cpu_openrisc_timer_update(OpenRISCCPU *cpu); void cpu_openrisc_count_start(OpenRISCCPU *cpu); void cpu_openrisc_count_stop(OpenRISCCPU *cpu); diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c index 16ef4b3e79..2153e7ea7e 100644 --- a/target-openrisc/interrupt.c +++ b/target-openrisc/interrupt.c @@ -30,26 +30,15 @@ void openrisc_cpu_do_interrupt(CPUState *cs) OpenRISCCPU *cpu = OPENRISC_CPU(cs); CPUOpenRISCState *env = &cpu->env; #ifndef CONFIG_USER_ONLY - if (env->flags & D_FLAG) { /* Delay Slot insn */ + + env->epcr = env->pc; + if (env->flags & D_FLAG) { env->flags &= ~D_FLAG; env->sr |= SR_DSX; - if (env->exception_index == EXCP_TICK || - env->exception_index == EXCP_INT || - env->exception_index == EXCP_SYSCALL || - env->exception_index == EXCP_FPE) { - env->epcr = env->jmp_pc; - } else { - env->epcr = env->pc - 4; - } - } else { - if (env->exception_index == EXCP_TICK || - env->exception_index == EXCP_INT || - env->exception_index == EXCP_SYSCALL || - env->exception_index == EXCP_FPE) { - env->epcr = env->npc; - } else { - env->epcr = env->pc; - } + env->epcr -= 4; + } + if (env->exception_index == EXCP_SYSCALL) { + env->epcr += 4; } /* For machine-state changed between user-mode and supervisor mode, diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c index 22d7cbec18..dd487bd0d1 100644 --- a/target-openrisc/mmu.c +++ b/target-openrisc/mmu.c @@ -32,7 +32,7 @@ int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu, int *prot, target_ulong address, int rw) { *physical = address; - *prot = PAGE_READ | PAGE_WRITE; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return TLBRET_MATCH; } @@ -187,7 +187,7 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env, if (ret == TLBRET_MATCH) { tlb_set_page(env, address & TARGET_PAGE_MASK, - physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, + physical & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); ret = 0; } else if (ret < 0) { diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c index cccbc0e939..be06c4565b 100644 --- a/target-openrisc/sys_helper.c +++ b/target-openrisc/sys_helper.c @@ -81,7 +81,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, case TO_SPR(0, 64): /* ESR */ env->esr = rb; break; - case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */ + case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); if (!(rb & 1)) { tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK); @@ -89,7 +89,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, env->tlb->dtlb[0][idx].mr = rb; break; - case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */ + case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); env->tlb->dtlb[0][idx].tr = rb; break; @@ -100,7 +100,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */ case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ break; - case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */ + case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); if (!(rb & 1)) { tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK); @@ -108,7 +108,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, env->tlb->itlb[0][idx].mr = rb; break; - case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */ + case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); env->tlb->itlb[0][idx].tr = rb; break; @@ -127,33 +127,31 @@ void HELPER(mtspr)(CPUOpenRISCState *env, break; case TO_SPR(10, 0): /* TTMR */ { + if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) { + switch (rb & TTMR_M) { + case TIMER_NONE: + cpu_openrisc_count_stop(cpu); + break; + case TIMER_INTR: + case TIMER_SHOT: + case TIMER_CONT: + cpu_openrisc_count_start(cpu); + break; + default: + break; + } + } + int ip = env->ttmr & TTMR_IP; if (rb & TTMR_IP) { /* Keep IP bit. */ - env->ttmr = (rb & ~TTMR_IP) + ip; + env->ttmr = (rb & ~TTMR_IP) | ip; } else { /* Clear IP bit. */ env->ttmr = rb & ~TTMR_IP; cs->interrupt_request &= ~CPU_INTERRUPT_TIMER; } - cpu_openrisc_count_update(cpu); - - switch (env->ttmr & TTMR_M) { - case TIMER_NONE: - cpu_openrisc_count_stop(cpu); - break; - case TIMER_INTR: - cpu_openrisc_count_start(cpu); - break; - case TIMER_SHOT: - cpu_openrisc_count_start(cpu); - break; - case TIMER_CONT: - cpu_openrisc_count_start(cpu); - break; - default: - break; - } + cpu_openrisc_timer_update(cpu); } break; @@ -162,7 +160,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, if (env->ttmr & TIMER_NONE) { return; } - cpu_openrisc_count_start(cpu); + cpu_openrisc_timer_update(cpu); break; default: @@ -214,11 +212,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, case TO_SPR(0, 64): /* ESR */ return env->esr; - case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */ + case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */ idx = spr - TO_SPR(1, 512); return env->tlb->dtlb[0][idx].mr; - case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */ + case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */ idx = spr - TO_SPR(1, 640); return env->tlb->dtlb[0][idx].tr; @@ -230,11 +228,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ break; - case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */ + case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */ idx = spr - TO_SPR(2, 512); return env->tlb->itlb[0][idx].mr; - case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */ + case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */ idx = spr - TO_SPR(2, 640); return env->tlb->itlb[0][idx].tr; diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 8908a2e32b..91c60ebaae 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -209,42 +209,49 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0) { target_ulong tmp_pc; - int lab = gen_new_label(); - TCGv sr_f = tcg_temp_new(); /* N26, 26bits imm */ tmp_pc = sign_extend((imm<<2), 26) + dc->pc; - tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); - if (op0 == 0x00) { /* l.j */ + switch (op0) { + case 0x00: /* l.j */ tcg_gen_movi_tl(jmp_pc, tmp_pc); - } else if (op0 == 0x01) { /* l.jal */ + break; + case 0x01: /* l.jal */ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); tcg_gen_movi_tl(jmp_pc, tmp_pc); - } else if (op0 == 0x03) { /* l.bnf */ - tcg_gen_movi_tl(jmp_pc, dc->pc+8); - tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab); - tcg_gen_movi_tl(jmp_pc, tmp_pc); - gen_set_label(lab); - } else if (op0 == 0x04) { /* l.bf */ - tcg_gen_movi_tl(jmp_pc, dc->pc+8); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab); - tcg_gen_movi_tl(jmp_pc, tmp_pc); - gen_set_label(lab); - } else if (op0 == 0x11) { /* l.jr */ + break; + case 0x03: /* l.bnf */ + case 0x04: /* l.bf */ + { + int lab = gen_new_label(); + TCGv sr_f = tcg_temp_new(); + tcg_gen_movi_tl(jmp_pc, dc->pc+8); + tcg_gen_andi_tl(sr_f, cpu_sr, SR_F); + tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE, + sr_f, SR_F, lab); + tcg_gen_movi_tl(jmp_pc, tmp_pc); + gen_set_label(lab); + tcg_temp_free(sr_f); + } + break; + case 0x11: /* l.jr */ tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); - } else if (op0 == 0x12) { /* l.jalr */ + break; + case 0x12: /* l.jalr */ tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); - } else { + break; + default: gen_illegal_exception(dc); + break; } - tcg_temp_free(sr_f); dc->delayed_branch = 2; dc->tb_flags |= D_FLAG; gen_sync_flags(dc); } + static void dec_calc(DisasContext *dc, uint32_t insn) { uint32_t op0, op1, op2; @@ -904,29 +911,33 @@ static void dec_misc(DisasContext *dc, uint32_t insn) case 0x27: /* l.addi */ LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); { - int lab = gen_new_label(); - TCGv_i64 ta = tcg_temp_new_i64(); - TCGv_i64 td = tcg_temp_local_new_i64(); - TCGv_i32 res = tcg_temp_local_new_i32(); - TCGv_i32 sr_ove = tcg_temp_local_new_i32(); - tcg_gen_extu_i32_i64(ta, cpu_R[ra]); - tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); - tcg_gen_trunc_i64_i32(res, td); - tcg_gen_shri_i64(td, td, 32); - tcg_gen_andi_i64(td, td, 0x3); - /* Jump to lab when no overflow. */ - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); - tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); - tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); - tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); - tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); - gen_exception(dc, EXCP_RANGE); - gen_set_label(lab); - tcg_gen_mov_i32(cpu_R[rd], res); - tcg_temp_free_i64(ta); - tcg_temp_free_i64(td); - tcg_temp_free_i32(res); - tcg_temp_free_i32(sr_ove); + if (I16 == 0) { + tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]); + } else { + int lab = gen_new_label(); + TCGv_i64 ta = tcg_temp_new_i64(); + TCGv_i64 td = tcg_temp_local_new_i64(); + TCGv_i32 res = tcg_temp_local_new_i32(); + TCGv_i32 sr_ove = tcg_temp_local_new_i32(); + tcg_gen_extu_i32_i64(ta, cpu_R[ra]); + tcg_gen_addi_i64(td, ta, sign_extend(I16, 16)); + tcg_gen_trunc_i64_i32(res, td); + tcg_gen_shri_i64(td, td, 32); + tcg_gen_andi_i64(td, td, 0x3); + /* Jump to lab when no overflow. */ + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab); + tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab); + tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY)); + tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE); + tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab); + gen_exception(dc, EXCP_RANGE); + gen_set_label(lab); + tcg_gen_mov_i32(cpu_R[rd], res); + tcg_temp_free_i64(ta); + tcg_temp_free_i64(td); + tcg_temp_free_i32(res); + tcg_temp_free_i32(sr_ove); + } } break; diff --git a/tests/tcg/openrisc/test_addc.c b/tests/tcg/openrisc/test_addc.c index 05d18f8ce5..a8f756a69b 100644 --- a/tests/tcg/openrisc/test_addc.c +++ b/tests/tcg/openrisc/test_addc.c @@ -7,9 +7,10 @@ int main(void) b = 0x01; c = 0xffffffff; - result = 1; + result = 0; __asm - ("l.addc %0, %1, %2\n\t" + ("l.add r1, r1, r0\n\t" /* clear carry */ + "l.addc %0, %1, %2\n\t" : "=r"(a) : "r"(b), "r"(c) ); @@ -22,7 +23,8 @@ int main(void) c = 0xffffffff; result = 0x80000001; __asm - ("l.addc %0, %1, %2\n\t" + ("l.add r1, r1, r0\n\t" /* clear carry */ + "l.addc %0, %1, %2\n\t" "l.movhi %2, 0x7fff\n\t" "l.ori %2, %2, 0xffff\n\t" "l.addc %0, %1, %2\n\t" diff --git a/tests/tcg/openrisc/test_addic.c b/tests/tcg/openrisc/test_addic.c index 4ba7432521..857aaa1330 100644 --- a/tests/tcg/openrisc/test_addic.c +++ b/tests/tcg/openrisc/test_addic.c @@ -6,9 +6,10 @@ int main(void) int result; a = 1; - result = 0x1; + result = 0x0; __asm - ("l.addic %0, %0, 0xffff\n\t" + ("l.add r1, r1, r0\n\t" /* clear carry */ + "l.addic %0, %0, 0xffff\n\t" : "+r"(a) ); if (a != result) { @@ -16,10 +17,11 @@ int main(void) return -1; } - a = 0x1; + a = -1; result = 0x201; __asm - ("l.addic %0, %0, 0xffff\n\t" + ("l.add r1, r1, r0\n\t" /* clear carry */ + "l.addic %0, %0, 0x1\n\t" "l.ori %0, r0, 0x100\n\t" "l.addic %0, %0, 0x100\n\t" : "+r"(a) |